0.1.0 • Published 9 years ago

react-mutant v0.1.0

Weekly downloads
-
License
MIT
Repository
-
Last release
9 years ago

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

FeatureMutantCortex
Access prop valuesStandard.getValue()
Works with React PropType validation out of the boxYesNo
Array & Hash methodsNoYes
Update Root Component easilyYesYes
CallbacksYesYes
Deeply Nested UpdatesNot yetYes
.getChanges().history() insteadYes
.didChange().set() returns false insteadYes
Batch updatesNot YetYes
.remove()NoYes
NPMYesYes
ES6NoYes
BowerNoYes
CDNNot YetNo

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");