Perplexityy
Perplexityy

Reputation: 569

Updating child component state in react

I'm having a lot of trouble updating the state of my child component, using props.

I have a parent component, called InputForm, which maintains a 2d array, which gets updated when the user fills out data in a form. This works correctly, however, I am trying to use this state variable to update the state of my child component, called Matrix. However, nothing I do seems to actually change the state of the Matrix component.

class InputForm extends Component {
  constructor(props) {
    super(props);
    this.matrix = React.createRef();
    this.state = {
      equation: null,
      integers: []
    };
  }

  addIntegers = v => {
    const newIntegers = this.state.integers.slice();
    newIntegers.push(v);
    this.setState({ integers: newIntegers });
    this.matrix.current.changeElements(this.state.integers);
  };

  render() {
    return (
      <div>
        <form onSubmit={this.mySubmitHandler}>
          <input
            type="text"
            name="equation"
            onChange={this.handleInputChange}
          />
        </form>
        <Matrix ref={this.matrix} values={this.state.integers} />
      </div>
    );
  }

class Matrix extends Component {
  state = {
    rows: 0,
    cols: 0,
    elements: [[]]
  };

  constructor(props) {
    super(props);
    this.setState({ elements: this.props.value });
  }

  changeElements = props => {
    this.setState({ elements: this.props.values });
    console.log(this.elements);
  };

Upvotes: 0

Views: 90

Answers (2)

syjsdev
syjsdev

Reputation: 1336

Because, this.setState (...) is asynchronous function. if you want to call this.matrix.current.changeElements(this.state.integers); function after updated the parent state, set the second argument of this.setState (...) to the callback function.

This is the fixed code

class InputForm extends Component {
...
  addIntegers = v => {
    const newIntegers = this.state.integers.slice();
    newIntegers.push(v);
    this.setState({ integers: newIntegers }, () => {     // use callback
        this.matrix.current.changeElements(this.state.integers);
    });
  };
...
class Matrix extends Component {
  constructor(props) {
    super(props);
    this.state = {
       rows: 0,
       cols: 0,
       elements: this.props.value || [[]] // try like this.
    };
  }

  changeElements = props => {
    // this.setState({ elements: this.props.values }); // wrong
    this.setState({ elements: props.values }, () => {
       console.log(this.state.elements);
    }); // maybe like this
  };

This is a simple example.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
    this.state = {
      value: "aaa",
    }
  };

  updateChild = () => {
    this.setState({value: "bbb"}, () => {
      this.child.current.changeElements(this.state.value);
    })
  };
  
  render() {
    return (
      <div>
        <button onClick = {this.updateChild} > Click here </button>
        <Child ref={this.child} values={this.state.value} />
      </div>
    );
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.values,
    };
  }

  changeElements = value => {
    this.setState({ value });
    console.log(value);
  };
  
  render() {
    console.log(this.state.value)
    return (
      <div>{this.state.value}</div>
    );
  }
}

ReactDOM.render( < App / > , document.getElementById('app'));
<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>
<div id="app"></div>

Upvotes: 0

Saqib Naseeb
Saqib Naseeb

Reputation: 741

In the parent component you are passing values as props

<Matrix ref={this.matrix} values={this.state.integers} />

while in the Matrix you are accessing:

constructor(props) {
    super(props);
    this.setState({ elements: this.props.value });
  }

where this.props.value is not there, you should access the this.props.values

Upvotes: 1

Related Questions