Reputation: 569
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
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
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