React state changed not re rendering child

use*_*581 0 reactjs

I Would like to bind two child field together. I have created change handler in parent class and passing state value in props of child. whenever i type something in textfield, Parent state and child props are updated i can see that in react dev tool, but child state is not reflected.

Below is my code

class Parent extends React.Component{

    constructor(props){
        super(props);
        this.state = {value: "test"};
        this.changeHandler = this.changeHandler.bind(this);
    }

    changeHandler(value){
        this.setState({value: value});
    }

    render(){
        return (
                <div>
                    <Child value={this.state.value} change={this.changeHandler}/>
                    <Child value={this.state.value} change={this.changeHandler}/>
                </div>
                );
    }
}

class Child extends React.Component{

    constructor(props){
        super(props);
        this.changeHandler = this.changeHandler.bind(this);
        this.state = {value: this.props.value};
    }

    changeHandler(e){
        this.setState({value:e.target.value});
        this.props.change(e.target.value);
    }

    render(){
        return (
                <input type="text" value={this.state.value} onChange={this.changeHandler} />
                );
    }

}

ReactDOM.render(<Parent/>, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

dan*_*die 5

It's because you are using

class Child extends React.Component{

    constructor(props){
        super(props);
        this.changeHandler = this.changeHandler.bind(this);
        // ...............  
        this.state = {value: this.props.value};
    }
    // ... 
}
Run Code Online (Sandbox Code Playgroud)

Your internal this.state.value is set only "once" on component mount phase.
(That means, whenever Parent -> this.state.value changes and causes the Child components to re-render, this.state = {value: this.props.value}; won't be invoked again)

Instead of using the state in Child component, use the this.props.value directly on your <Input /> field.

<input type="text" value={this.props.value} onChange={this.changeHandler} />
Run Code Online (Sandbox Code Playgroud)

So the flow is, someone types something in Child.input, which tells Parent to update the state, and the change is trickled back down to your Child -> this.props.value.

And then you notify Parent by calling the passed this.props.changeHandler.

So the final, Child component would look like following.

class Child extends React.Component{
    constructor(props){
        super(props);
        this.changeHandler = this.changeHandler.bind(this);
    }

    changeHandler(e){
        this.props.changeHandler({value:e.target.value});
    }

    render(){
        return (
          <input type="text" value={this.props.value} onChange={this.changeHandler} />
        );
    }

}
Run Code Online (Sandbox Code Playgroud)

If you use the ES6 "arrow functions" syntax, you can make it smaller, removing the need for this.changeHandler = this.changeHandler.bind(this).
(It's because an arrow function doesn't create its own this but uses calling context's this)

class Child extends React.Component{
    constructor(props){
        super(props);
    }

    changeHandler = (e) => {
        this.props.changeHandler({value:e.target.value});
    }

    render(){
        return (
          <input type="text" value={this.props.value} onChange={this.changeHandler} />
        );
    }

}
Run Code Online (Sandbox Code Playgroud)

Or you can call it directly from onChange.

class Child extends React.Component {
  render() {
    return (
      <input
        type="text"
        value={this.props.value}
        onChange={this.props.changeHandler}
      />
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我们可以进一步将其转换为功能组件(不要使用“功能”组件,因为它与功能编程没有任何关系),

function Child({ value, changeHandler}) {
  return <input type="text" value={value} onChange={changeHandler} />
}

// or
const Child = ({value, changeHandler}) => 
  <input type="text" value={value} onChange={changeHandler} />
Run Code Online (Sandbox Code Playgroud)

并且在使用时const Child = ...,请确保已将其声明为BEFORE Parent。但是,当您使用时function ChildParent由于JavaScript提升的工作原理,它可能会在之前或之后显示。

最后,不需要更改Parent