HaroonGhawsi
7/5/2016 - 1:57 PM

React Props Proposal

React Props Proposal

React Props Proposal

First read these tweets:

and this doc:

The problem

1. It's not clear when to use props vs state

After spending some time with React it makes sense, however for newcomers the two seem interchangeable IMO.

2. The solution for the anti-pattern is ugly

Components should feel native. A browser shipped component uses disabled not initialDisabled. The proposed solution leaks implementation details to the API. The consumer doesn't care if we use state or props or whatever. They just want to pass data to a component and the component should handle it.

The proposal

1. Remove setProps and treat props as immutable

This will help make it clear that props is meant to:

  • allow input into the component from the consumer (another developer)
  • to be read-only data, not for tracking internal state (well suited for initial state, onEvent type functions, etc)

2. Facilitate merging of initial props to state

Goals:

  • to provide a clean API for the component that is exposed to the consumer
  • discourage using props that are meant to be initial state after component is mounted
/** @jsx React.DOM */

var Example = React.createClass({
    getDefaultProps: function () {
        return {
            // Properties inside `__state` will be populated by props passed
            // by consumer then get merged into `this.state`        
            __state: {
                disabled: false
            },
            onToggle: null
        };
    },

    getInitialState: function () {
        return {
            message: ''
        };
    },

    handleDisabledChange: function () {
        var disabled = this.refs.disabled.getDOMNode().checked;
        if (typeof this.props.onToggle === 'function') {
            this.props.onToggle(disabled);
        }
        this.setState({
            disabled: disabled
        });
    },

    handleMessageChange: function () {
        this.setState({
            message: this.refs.message.getDOMNode().value
        });
    },

    render: function () {
        return (
            <div>
                <input ref="disabled"
                        type="checkbox"
                        checked={this.state.disabled}
                        onChange={this.handleDisabledChange}/>
                <input ref="message"
                        type="text"
                        value={this.state.message}
                        disabled={this.state.disabled}
                        onChange={this.handleMessageChange}/>
                <div ref="outlet">{this.state.message}</div>
            </div>
        );
    }
});

/*
 * `disabled` can be passed in as an attribute providing an intial state
 *
 * `onToggle` can also be passed in to handle `disabled` being changed
 *
 * `message` cannot be passed in, it is used as internal state only
 */
React.renderComponent(<Example disabled={true} onToggle={function (disabled) { console.log(disalbed); }}/>, document.body);