Updating State From Child Component Onclick
How to update the state of a parent component from a child component is one of the most commonly asked React questions.
Imagine you're trying to write a simple recipe box application, and this is your code so far:
import React from "react";
import ReactDOM from "react-dom";
import RecipeBox from "./RecipeBox";
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<RecipeBox />
</React.StrictMode>,
rootElement
);
import React from "react";
export default class RecipeBox extends React.Component {
constructor(props) {
super(props);
this.state = {
input: "",
recipeList: [
{
recipe: "Tacos",
directions: "make tacos",
ingredients: ["meat"]
},
{
recipe: "pizza",
directions: "bake",
ingredients: ["dough"]
}
]
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
handleSubmit() {
const newRecipe = this.state.recipelist[0].recipe;
setState({
recipeList[0].recipe: newRecipe
});
}
render() {
const ITEMS = this.state.recipeList.map(({ directions }) => (
<li>{directions}</li>
));
return (
<div>
<EditList
input={this.state.input}
handleChange={this.handleChange}
onSubmit={this.handleSubmit}
/>
<ul>{ITEMS}</ul>
</div>
);
}
}
class EditList extends React.Component {
render() {
return (
<div>
<input
type='text'
value={this.props.input}
onChange={this.props.handleChange}
/>
<button onClick={this.props.onSubmit}>Submit</button>
</div>
);
}
}
Eventually you want handleChange
to capture what the user enters and update specific recipes.
But when you try to run your app, you see a lot of errors in the terminal and dev console. Let's take a closer look at what's going on.
Fixing errors
First in handleSubmit
, setState
should be this.setState
:
handleSubmit() {
const newRecipe = this.state.recipelist[0].recipe;
this.setState({
recipeList[0].recipe: newRecipe
});
}
You're already prop drilling, or passing things from the parent RecipeBox
component to its child EditList
properly. But when someone enters text into the input box and clicks "Submit", the state isn't updated the way you expect.
How to update the state from a child component
Here you're running into issues because you're trying to update the state of a nested array (recipeList[0].recipe: newRecipe
). That won't work in React.
Instead, you need to create a copy of the full recipeList
array, modify the value of recipe
for the element you want to update in the copied array, and assign the modified array back to this.state.recipeList
.
First, use the spread syntax to create a copy of this.state.recipeList
:
handleSubmit() {
const recipeList = [...this.state.recipeList];
this.setState({
recipeList[0].recipe: newRecipe
});
}
Then update the recipe for the element you want to update. Let's do the first element as a proof of concept:
handleSubmit() {
const recipeList = [...this.state.recipeList];
recipeList[0].recipe = this.state.input;
this.setState({
recipeList[0].recipe: newRecipe
});
}
Finally, update the current recipeList
with your new copy. Also, set input
to an empty string so the textbox is empty after users click "Submit":
handleSubmit() {
const recipeList = [...this.state.recipeList];
recipeList[0].recipe = this.state.input;
this.setState({
recipeList,
input: ""
});
}
Subscribe to my newsletter
Read articles from freeCodeCamp directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
freeCodeCamp
freeCodeCamp
Learn to code. Build projects. Earn certifications—All for free.