简体   繁体   中英

React.js properties

I am currently going through the documentation of React.js and have a question about this.props , which according to the docs should be considered immutable and only pushed downwards down the ownership tree since bubbling custom events upwards is discouraged.

Say that I have a UI where the state of a component in the header of the page should be shared with another component that is nested somewhere in the body of the page, let's take a simple checkbox that represents some specific state that will influence the visibility of some nested spans or divs.
The only I way I currently see this achieved is by creating a state property that is pushed downwards from the top element to the child elements.

The two related questions I have with this is:

  1. Does this mean that I should create one component that owns the entire page? (Is rendering the entire page with a single owner component an acceptable thing to do? I understand the concepts of Virtual DOM and diffing so I assume it's not a problem, still I'd like some confirmation in case I miss out on something relevant);
  2. Is it ok to change the property on this.props when clicking the checkbox, in order to re-render the other components on the page? This doesn't make the props immutable (perhaps they mean just that setting new props on this.props down the chain is not accepted to avoid an untransparent stack trace in case of bugs, but changing the value of a state property is?).

Some confirmation would be appreciated.
Thanks.

I guess having one master component isn't an issue. The docs suggest that you find the topmost component that can supply it's children with the needed data - and this could easily be the toplevel master component. As I understand this you would have a master component for your main page - that should be the only one that uses state , the children just render what they are given in props . So no, props should not be altered by a child that doesn't own the data, it is the topmost components prerogative to do so. Let's say you have another widget on the page that only cares for a distinct set of data you would make this the root of another tree that fetches data and sets it's state and the props of it's children.

Here is a crappy graph for this situation:

App -(props)-> ItemList -(props)-> Item -(props)-> Photo 
 +  +                               |
 +   ++++++++++                     |----(props)-> LikeButton
 +            +                     |
(fetch)       +                     |
 +            +                     * ---(props)-> Description
 ++(setState)++

Widget -(props)-> Whether

However it gets more interesting when facebook's graphql is finalized and every component can declare the needed data on it's own, I'm looking forward to it. But until then the toplevel component has to know which data every child needs and all the parent nodes need to hand this data down.

1) It is fine to have one parent for the whole page, but is not always necessary. It depends on if it is necessary to share the state between components.

2) You never want to alter props via this.props.someValue = newValue . If you need to modify the parent state from a child component, it should always be done with a callback. The example below shows how to share the checkbox state between multiple components using the callback function handleClick to modify the state of is_checked .

JSFiddle of example: https://jsfiddle.net/mark1z/o7noph4y/

var Parent = React.createClass({
    getInitialState: function(){
        return ({is_checked: 0})
    },
    handleClick: function(){
        this.setState({is_checked: !this.state.is_checked})
    },
    render: function(){
        return (
            <div>
                <CheckBox is_checked={this.state.is_checked} handleClick={this.handleClick}/>
                <OtherComponent is_checked={this.state.is_checked} />
            </div>
        );
    }
});

var CheckBox = React.createClass({
    render: function() {
        return (
            <input type="checkbox" onChange={this.props.handleClick}> Show other component </input>

        );
    }
});


var OtherComponent = React.createClass({
    render: function() {
        return (
            <div style={{marginTop: 20}}> 
                {this.props.is_checked ? 'The checkbox is ticked' :  'The checkbox is not ticked'}
            </div>

        );
    }
});
React.render(<Parent />, document.getElementById('container'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM