razi3lCast
razi3lCast

Reputation: 115

Is it better to duplicate part of the parent state to children?

As my application grows more and more there are more discussion in my head about managing the component state. I have a big parent component which include a few child components so each of them render specific set of data.Until now in other components I was strictly updating the parent state only and not duplicating the state at all as I read in the docs and etc.. As now my children render a few inputs each and updates the parent state object. Question - Is that correct or I should duplicate some of the parent state in my children so the inputs use them directly and onBlur action they update the parent? The benefit is that it will render the parent only 1 time onBlur as it is at the moment updating directly the parent state it is rendered on each user input.

I tried both cases and the performance using the react profiler is more for the duplicating state idea -only because the parent is rendering only once not on each user onchange input. That's why I want to ask if it's something wrong. Each other small component which is part of the big one is a PureComponent and don't do useless rendering.

class TestParent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            testObject: {
                ...many properties
            }
        };
    }
onChange = (evt) => {
thi.setState({
 testObject: { ...testObject, [evt.target.id]: evt.target.value
})

}
render(){
 <ChildComponent1 onChange={this.onChange} prop1={state.testObject.value1} prop2={state.testObject.value2}
prop3={state.testObject.value3}> </ChildComponent1>

 <ChildComponent2 onChange={this.onChange} prop4={state.testObject.value4}> </ChildComponent2>

 <ChildComponent3 onChange={this.onChange} prop5={state.testObject.value5}> </ChildComponent3>

<ChildComponent6 onChange={this.onChange} prop6={state.testObject.value6}> </ChildComponent4>

<ChildComponent7 onChange={this.onChange} prop7={state.testObject.value7}> </ChildComponent7>

<textbox value={this.state.testObject} />
}


class ChildComponent1 extends React.PureComponent {

    constructor(props) {
        super(props);
    }

}
render(){
 <Input onChange={this.props.onChange} value={this.props.prop1}</Input>
 <Input onChange={this.props.onChange} value={this.props.prop2}> </Input>
 <Input onChange={this.props.onChange} value={this.props.prop3}> </Input>
}

Upvotes: 1

Views: 724

Answers (1)

Willman.Codes
Willman.Codes

Reputation: 1413

To answer your question: Whether you should take a prop passed to a child and add it to state on componentDidMount then update parent state onBlur or onSubmit within the child component?

Best practice would be to only pass state from parent component to child component that is either shared by children of the parent or is used by the parent itself.

In your example it would be best to manage the input value state within the child component then to use a callback function to setState on the parent component on blur.

Simplified example:

class Parent extends React.Component {
    state = {
        child1State:'' // initializing state is not strictly necessary 
    };
    
    changeParentState = (value)=>{
        this.setState(value)
    }

    render(){
        return(
            <div>
                <Child1Component 
                    changeParentState={this.changeParentState}
                />
                {this.state.child1State}
            </div>
        )
    }
}

class Child1Component extends React.PureComponent {
    state={
        inputValue:''
    }
    handleBlur=()=>{
        this.props.changeParentState({child1State : this.state.inputValue})
    }
    render(){
        return (
            <input 
                onChange={(e)=> this.setState({inputValue:e.target.value})}
                value={this.state.inputValue}
                onBlur={this.handleBlur}
            />
        )
    }
}

ReactDOM.render(
    <Parent />,
    document.getElementById("react")
);
<div id='react'></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 1

Related Questions