react-mutant

0.1.0 • Public • Published

React-Mutant

React-Mutant piggybacks your props to make nested updates easy in React. Instead of passing 'update' handlers into all components needing to update root component properties, React-Mutant can be used instead.

  • Simpler solution than Flux, though not as robust. Ideal for smaller to mid-size applications or isolated components
  • Inspired by Cortex http://https://github.com/mquan/cortex
  • Built-in listener for root component/top-down updates
  • Provide your own mixin methods to extend the React-Mutant instance

Example

JSFiddle Live Example: http://jsfiddle.net/69z2wepo/2975/

// Create Mutant Objects with default properties
var postMutant = new Mutant({
	id: 0,
	title: "",
	content: ""
});
var commentsMutant = new Mutant({
	comments: []
});

// Root-level component
var App = React.createClass({
    // validate properties as your normally would
    propTypes: {
        post: React.PropTypes.shape({
            id: React.PropTypes.number,
            title: React.PropTypes.title,
            content: React.PropTypes.content
        }),
        comments: React.PropTypes.shape({
            comments: React.PropTypes.array
        })
    },
    // set default props to Mutant objects
    getDefaultProps: function () {
		return {
			post: postMutant,
			comments: commentsMutant
		}
	},
    // listen to 'update' events, pass in updated mutant and set root props to new mutant
    componentWillMount: function () {
        var self = this;
        postMutant.mutant.on("update", function (newMutant) {
            self.setProps({post: newMutant});
        });
        commentsMutant.mutant.on("update", function (newMutant) {
            self.setProps({comments: newMutant});
        });
    },
    // {...this.props.post} = mutant object we created for post
    // {...this.props.comments} = mutant object we created for comments
	render: function () {
        return (
			<div className="app">
				<Post {...this.props.post} />
				<Comments {...this.props.comments} />
			</div>
		);
	}
});

var Post = React.createClass({
	componentDidMount: function () {
	  // once mounted, use post.mutant.set to update props and trigger root-level 'update'
        this.props.mutant.set({id: 1, title: "title", content: "content"});
    },
    render: function () {
		return (
			<div className="post">
				<h1>{this.props.title}</h1>
				<p>{this.props.content}</p>
			</div>
		);
	}
});

var Comments = React.createClass({
	add: function () {
        var current = this.props.comments;
        current.push({username: "me", date: "now", comment: "comment"});
        this.props.mutant.set({comments: current});
    },
    remove: function (index, e) {   
        var current = this.props.comments;
        current.splice(index, 1);
        this.props.mutant.set({comments: current});
    },
    render: function () {
		var i = -1;
        var remove = this.remove;
        var comments = this.props.comments || [];
		var list = comments.map(function (comment) {
			i++;
            comment.index = i;
            return <Comment key={i} {...comment} remove={remove} />
		});
		return (
			<div className="comments">
                <button onClick={this.add}>Add Comment</button>
				{list}
			</div>
		);
	}
});

var Comment = React.createClass({
    propTypes: {
		index: React.PropTypes.number,
        username: React.PropTypes.string,
		date: React.PropTypes.string,
		comment: React.PropTypes.string
	},
	render: function () {
		return (
			<div className="comment">
                <div>{this.props.index}</div>
				<div>{this.props.username}</div>
				<div>{this.props.date}</div>
				<div>{this.props.comment}</div>
                <button onClick={this.props.remove.bind(null, this.props.index)}>Remove</button>
			</div>
		);
	}
});

React.render(<App />, document.getElementById("app"));

Cortex comparison

Feature Mutant Cortex
Access prop values Standard .getValue()
Works with React PropType validation out of the box Yes No
Array & Hash methods No Yes
Update Root Component easily Yes Yes
Callbacks Yes Yes
Deeply Nested Updates Not yet Yes
.getChanges() .history() instead Yes
.didChange() .set() returns false instead Yes
Batch updates Not Yet Yes
.remove() No Yes
NPM Yes Yes
ES6 No Yes
Bower No Yes
CDN Not Yet No

Key Differences

The three primary reasons for creating React-Mutant over Cortex are:

  1. No need to use .getValue() when accessing prop values
  2. Works with React.PropTypes validation out of the box
  3. Lighter objects by not including Hash/Array methods

Nested Updates

Also, though not currently supported, future releases would like to include deeply nested updates.

So instead of:

mymutant.mutant.set({root: {level1: {level2: {level3: "newvalue"}}}});

You'll be able to:

mymutant.mutant.root.level1.level2.level3.set("newvalue");

Readme

Keywords

Package Sidebar

Install

npm i react-mutant

Weekly Downloads

1

Version

0.1.0

License

MIT

Last publish

Collaborators

  • jessedrelick