Reputation: 711
I'm trying to write a React app in which a parent component passes a callback function to a child component, the callback function is invoked and passed an argument, and it updates a state variable in the parent component, setting it to the argument. But I keep running into this error:
Warning: Cannot update during an existing state transition (such as within
render
). Render methods should be a pure function of props and state.
I've found other questions on here about this and have read the explanations of what the error means, but all the explanations of how to work around it involve more complex component structures that I found hard to follow as I'm only just starting out with React. I was hoping someone could show me how to modify this simple component structure to do what I want to do while avoiding that error (I'm doing this in a codepen.io environment, if that matters):
class Parent extends React.Component {
constructor(props) {
super(props)
this.state = { word: 'hello' }
}
myCallback = (dataFromChild) => {
this.setState({ word: dataFromChild })
}
render() {
return (
<div>
<p>{this.state.word}</p>
<Child callbackFromParent={this.myCallback} />
</div>
)
}
}
function Child(props) {
return (
<div>
<button onClick={props.callbackFromParent('goodbye')}>Say goodbye</button>
</div>
)
}
// ========================================
ReactDOM.render(<Parent />, document.getElementById('root'));
Upvotes: 0
Views: 3428
Reputation: 15146
Add a ()
for myCallback function
myCallback = dataFromChild => () => {
Try the in-text demo:
function Child(props) {
return (
<div>
<button onClick={props.callbackFromParent("goodbye")}>Say goodbye</button>
</div>
);
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = { word: "hello" };
}
myCallback = dataFromChild => () => {
this.setState({ word: dataFromChild });
};
render() {
return (
<div>
<p>{this.state.word}</p>
<Child callbackFromParent={this.myCallback} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
Upvotes: 1