Universe Utilities for react
Provides meteor react modules for universe:modules
Mapping all available modules like require('react/*') and of course require('react') to system modules.
import React from 'react'; import ReactDOM from 'react-dom'; import AutoFocusMixin from 'react/lib/AutoFocusMixin';
It's useful for importing components from npm by universe:modules-npm. Package universe:modules-npm allows to replace npm dependencies onto universe:modules dependencies
Universe Mixins for React
AutorunMixin
1import {AutorunMixin} from '{universe:utilities-react}'; 2 3// Any function prefixed with 'autorun' is executed in componentWillMount. 4// It will create Computation object. 5// Computation object is stopped in componentWillUnmount. 6 7export default React.createClass({ 8 mixins: [AutorunMixin], 9 10 // 'Anonymous' autorun. 11 autorun () { 12 // Reactive context here. 13 this.setState({ 14 name: Session.get('name') || 'Anonymous' 15 }); 16 }, 17 18 // 'IsLoggedIn' autorun. 19 autorunIsLoggedIn () { 20 this.setState({ 21 isLoggedIn: !!Metor.userId() 22 }); 23 }, 24 25 render () { 26 return ( 27 <div> 28 <p>Session variable: {this.state.name}</p> 29 <p>Is user logged in? {'' + this.state.isLoggedIn}</p> 30 <button onClick={this.invalidate}>Click to invalidate autoruns</button> 31 </div> 32 ); 33 }, 34 35 invalidate () { 36 this.autorunComputation.invalidate(); 37 this.autorunIsLoggedInComputation.invalidate(); 38 } 39});
DualLinkMixin
1import {DualLinkMixin} from '{universe:utilities-react}'; 2 3// Create or get dualLink from cache. 4// var dualLink = this.dualLink(name = 'default') 5// 6// Overwrite local state with object 7// dualLink.setLocal(object) 8// Overwrite remote state with object 9// dualLink.setRemote(object) 10// 11// Overwrite field in local state with value 12// dualLink.setLocal(field, value) 13// Overwrite field in remote state with value 14// dualLink.setRemote(field, value) 15// 16// Removes local state 17// dualLink.clear() 18// 19// Check for any value in both state 20// dualLink.isEmpty() 21// 22// Creates value link (changes are saved in local state) 23// dualLink.valueLink(field) 24// 25// Get two states merged 26// dualLink.get() 27// Get field from both states (local state has higher priority than remote) 28// dualLink.get(field) 29// 30// Get field from local state 31// dualLink.getLocal(field) 32// Get field from remote state 33// dualLink.getRemote(field) 34 35export React.createClass({ 36 mixins: [DualLinkMixin], 37 38 componentWillMount () { 39 this.dualLink().setRemote(this.props.user); 40 }, 41 42 componentWillReceiveProps (props) { 43 this.dualLink().clear(); 44 this.dualLink().setRemote(props.user); 45 }, 46 47 render () { 48 const dualLink = this.dualLink(); 49 50 if (dualLink.isEmpty()) { 51 return ( 52 <p>Loading...</p> 53 ); 54 } 55 56 return ( 57 <div> 58 <p>Id: {dualLink.get('id')}</p> 59 <p>Name: {dualLink.get('name')}</p> 60 </div> 61 ); 62 } 63});
SubscriptionMixin
1import {AutorunMixin, SubscriptionMixin} from '{universe:utilities-react}'; 2 3// Subscribe for publication 4// this.subscribe(publicationName, ...args) 5// 6// Check for readiness of single subscription 7// this.subscriptionReady(publicationName) 8// 9// Check for readiness of all subscriptions 10// this.subscriptionsReady() 11 12export default React.createClass({ 13 mixins: [SubscriptionMixin, AutorunMixin], 14 15 autorunUsers () { 16 this.subscribe('users'); 17 this.setState({ 18 users: Meteor.users.find().fetch() 19 }); 20 }, 21 22 render () { 23 if (!this.subscriptionsReady()) { 24 return ( 25 <p>Loading...</p> 26 ); 27 } 28 29 return ( 30 <ul> 31 {this.state.users} 32 </ul> 33 ); 34 } 35});
Complete example
1import {AutorunMixin, DualLinkMixin, SubscriptionMixin} from '{universe:utilities-react}'; 2 3export default React.createClass({ 4 mixins: [SubscriptionMixin, DualLinkMixin, AutorunMixin], 5 6 propTypes: { 7 id: React.PropTypes.string.isRequired 8 }, 9 10 autorunPost () { 11 const id = this.props.id; 12 13 this.subscribe('post', id); 14 this.dualLink().setRemote(Posts.findOne(id)); 15 }, 16 17 render () { 18 if (!this.subscriptionsReady()) { 19 return ( 20 <p>Loading...</p> 21 ); 22 } 23 24 const dualLink = this.dualLink(); 25 26 return ( 27 <div> 28 <input type="text" valueLink={dualLink.get('title')}> 29 <input type="text" valueLink={dualLink.get('text')}> 30 <button onClick={this.submit}>Save</button> 31 </div> 32 ); 33 }, 34 35 submit () { 36 Posts.update({ 37 _id: this.props.id 38 }, { 39 $set: this.dualLink().get() 40 }); 41 } 42});
Helpers
classNames
A simple utility for conditionally joining classNames together
1import {classNames} from '{universe:utilities-react}'; 2 3classNames('foo', 'bar'); // => 'foo bar' 4classNames('foo', { bar: true }); // => 'foo bar' 5classNames({ foo: true }, { bar: true }); // => 'foo bar' 6classNames({ foo: true, bar: true }); // => 'foo bar' 7 8// lots of arguments of various types 9classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }) // => 'foo bar baz quux' 10 11// other falsy values are just ignored 12classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
- based on JedWatson/classnames
executionEnvironment
Simple helpers around environment with information like: canUseDOM, canUseWorkers, canUseEventListeners, canUseViewport
1import {executionEnvironment} from '{universe:utilities-react}'; 2 3console.log(executionEnvironment.canUseDOM); 4console.log(executionEnvironment.canUseWorkers); 5console.log(executionEnvironment.canUseEventListeners); 6console.log(executionEnvironment.canUseViewport);
objectAssign
Ponyfill: A polyfill that doesn't overwrite the native method
1import {objectAssign} from '{universe:utilities-react}'; 2objectAssign({foo: 0}, {bar: 1}); 3//=> {foo: 0, bar: 1} 4 5// multiple sources 6objectAssign({foo: 0}, {bar: 1}, {baz: 2}); 7//=> {foo: 0, bar: 1, baz: 2} 8 9// overwrites equal keys 10objectAssign({foo: 0}, {foo: 1}, {foo: 2}); 11//=> {foo: 2} 12 13// ignores null and undefined sources 14objectAssign({foo: 0}, null, {bar: 1}, undefined); 15//=> {foo: 0, bar: 1}
objectAssign(target, source, [source, ...])
Assigns enumerable own properties of source objects to the target object and returns the target object. Additional source objects will overwrite previous ones.
- more here: ES6 spec - Object.assign
- based on sindresorhus/object-assign
cloneWithProps
Stand-alone React cloneWithProps util that works with multiple versions of React
1import {cloneWithProps} from '{universe:utilities-react}'; 2cloneWithProps(<MyComponent oldProp='hi'/> { newProp: 'hello' })
This is tested with React 0.9 to 0.13, and adds a trivial amount of code to get everything to work.
- based on react-clonewithprops