├── README.md ├── connect-meteor-data-tests.jsx ├── connect-meteor-data.jsx └── package.js /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rclai/connect-meteor-data/b6f686561044ad8bc2927ef636ef8ad0efd2fc24/README.md -------------------------------------------------------------------------------- /connect-meteor-data-tests.jsx: -------------------------------------------------------------------------------- 1 | getInnerHtml = function (elem) { 2 | // clean up elem.innerHTML and strip data-reactid attributes too 3 | return canonicalizeHtml(elem.innerHTML).replace(/ data-reactid=".*?"/g, ''); 4 | }; 5 | 6 | Tinytest.add('react-meteor-data - basic track', function (test) { 7 | var div = document.createElement("DIV"); 8 | 9 | var x = new ReactiveVar('aaa'); 10 | 11 | var Foo = React.createClass({ 12 | render() { 13 | return {this.props.x}; 14 | } 15 | }); 16 | 17 | var MeteorizedFoo = connectMeteorData(function() { 18 | return { 19 | x: x.get() 20 | } 21 | })(Foo); 22 | 23 | React.render(, div); 24 | test.equal(getInnerHtml(div), 'aaa'); 25 | 26 | x.set('bbb'); 27 | Tracker.flush({_throwFirstError: true}); 28 | test.equal(getInnerHtml(div), 'bbb'); 29 | 30 | test.equal(x._numListeners(), 1); 31 | 32 | React.unmountComponentAtNode(div); 33 | 34 | test.equal(x._numListeners(), 0); 35 | }); 36 | 37 | Tinytest.add('react-meteor-data - track based on props', function (test) { 38 | var div = document.createElement("DIV"); 39 | 40 | var xs = [new ReactiveVar('aaa'), 41 | new ReactiveVar('bbb'), 42 | new ReactiveVar('ccc')]; 43 | 44 | var Foo = React.createClass({ 45 | render() { 46 | return {this.props.x}; 47 | } 48 | }); 49 | 50 | var MeteorizedFoo = connectMeteorData(function(props) { 51 | return { 52 | x: xs[props.n].get() 53 | }; 54 | })(Foo); 55 | 56 | var comp = React.render(, div); 57 | 58 | test.equal(getInnerHtml(div), 'aaa'); 59 | xs[0].set('AAA'); 60 | test.equal(getInnerHtml(div), 'aaa'); 61 | Tracker.flush({_throwFirstError: true}); 62 | test.equal(getInnerHtml(div), 'AAA'); 63 | 64 | { 65 | let comp2 = React.render(, div); 66 | test.isTrue(comp === comp2); 67 | } 68 | 69 | test.equal(getInnerHtml(div), 'bbb'); 70 | xs[1].set('BBB'); 71 | Tracker.flush({_throwFirstError: true}); 72 | test.equal(getInnerHtml(div), 'BBB'); 73 | 74 | React.render(, div); 75 | test.equal(getInnerHtml(div), 'ccc'); 76 | xs[2].set('CCC'); 77 | Tracker.flush({_throwFirstError: true}); 78 | test.equal(getInnerHtml(div), 'CCC'); 79 | 80 | React.render(, div); 81 | test.equal(getInnerHtml(div), 'AAA'); 82 | 83 | React.unmountComponentAtNode(div); 84 | }); 85 | 86 | Tinytest.add('react-meteor-data - track based on props and context', function (test) { 87 | var div = document.createElement("DIV"); 88 | 89 | var x = new ReactiveVar('aaa'); 90 | 91 | var Foo = React.createClass({ 92 | render() { 93 | return ( 94 | {this.props.x}{this.props.y} 95 | ); 96 | } 97 | }); 98 | 99 | var MeteorizedFoo = connectMeteorData(function(props, context) { 100 | return { 101 | y: context.x, 102 | x: x.get() 103 | } 104 | })(Foo); 105 | 106 | MeteorizedFoo.contextTypes = { 107 | x: React.PropTypes.string 108 | }; 109 | 110 | var Bar = React.createClass({ 111 | childContextTypes: { 112 | x: React.PropTypes.string 113 | }, 114 | 115 | getChildContext() { 116 | return { 117 | x: 'bbb' 118 | } 119 | }, 120 | 121 | render() { 122 | return ( 123 | 124 | ) 125 | } 126 | }); 127 | 128 | React.render((), div); 129 | test.equal(getInnerHtml(div), 'aaabbb'); 130 | x.set('CCC'); 131 | Tracker.flush({_throwFirstError: true}); 132 | test.equal(getInnerHtml(div), 'CCCbbb'); 133 | React.unmountComponentAtNode(div); 134 | 135 | test.equal(x._numListeners(), 0); 136 | }); 137 | -------------------------------------------------------------------------------- /connect-meteor-data.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * A React component composer function creator used to connect 3 | * Meteor reactive data to any React component 4 | * @param {function} getMeteorData - a function that returns as object 5 | * with Meteor reactive data sources 6 | * @return {function} - a function used to wrap React components 7 | */ 8 | connectMeteorData = function(getMeteorData) { 9 | if (!getMeteorData || typeof getMeteorData !== 'function') { 10 | throw new Error('You need to supply a function returning an ' + 11 | 'object of Meteor reactive data sources.'); 12 | } 13 | 14 | /** 15 | * Returns wrapped component connected with Meteor reactive 16 | * data sources so that you don't have to access the data with 17 | * `this.data` but rather with `this.props`. 18 | * @param {React.Component} WrappedComponent - A React component 19 | * @param {object} optional - an object with acceptable context types 20 | * @return {React.Component} The resulting React component 21 | */ 22 | return function wrapReactComponent(WrappedComponent, contextTypes = {}) { 23 | if (!WrappedComponent || !(WrappedComponent instanceof React.constructor)) { 24 | throw new Error('You must pass a React component into this function.'); 25 | } 26 | 27 | return React.createClass({ 28 | displayName: 'MeteorizedComponent', 29 | 30 | mixins: [ReactMeteorData], 31 | 32 | contextTypes: contextTypes, 33 | 34 | getMeteorData() { 35 | return getMeteorData.call(this, this.props, this.context); 36 | }, 37 | 38 | render() { 39 | return ( 40 | 41 | ); 42 | } 43 | }); 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'lai:connect-meteor-data', 3 | version: '0.0.1', 4 | // Brief, one-line summary of the package. 5 | summary: 'Connect your React components with Meteor reactive data.', 6 | // URL to the Git repository containing the source code for this package. 7 | git: 'https://github.com/rclai/meteorize-react-component.git', 8 | // By default, Meteor will default to using README.md for documentation. 9 | // To avoid submitting documentation, set this field to null. 10 | documentation: 'README.md' 11 | }); 12 | 13 | Package.onUse(function(api) { 14 | api.versionsFrom('1.1.0.2'); 15 | api.use([ 16 | 'react', 17 | 'react-meteor-data' 18 | ]); 19 | api.addFiles('connect-meteor-data.jsx'); 20 | api.export('connectMeteorData'); 21 | }); 22 | 23 | Package.onTest(function(api) { 24 | api.use('tinytest'); 25 | api.use('reactive-var'); 26 | api.use('lai:connect-meteor-data'); 27 | api.use('jsx'); 28 | api.use('tracker'); 29 | api.use('test-helpers'); 30 | api.addFiles('connect-meteor-data-tests.jsx', 'client'); 31 | }); 32 | --------------------------------------------------------------------------------