universe:utilities-react

v0.5.4Published 8 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

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.

- 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