I'm passing some values from my state in the App component to the GetWordContainer component as props. With these props, I set the state in my child component. However, the state in GetWordContainer only updates once. How can I have the state in the child component continue to update when the state in App.js changes?
App.js
class App extends Component {
state = {
redirect: {},
word: '',
error: '',
info: [],
partOfSpeech: [],
versions: [],
shortdef: "",
pronunciation: "",
}
setRedirect = redirect =>{{
this.setState({redirect})
}
// console.log(this.state.redirect);
console.log(this.state.word);
}
handleUpdate = values =>
this.setState({...values})
render() {
return (
<>
<Route
render={ routeProps => <Redirector redirect={this.state.redirect} setRedirect={this.setRedirect} {...routeProps} />}
/>
<header>
<nav>
<Link to='/'>My Dictionary</Link>
</nav>
</header>
<main>
<Route
render = { routeProps =>
!routeProps.location.state?.alert ? '' :
<div>
{ routeProps.location.state.alert }
</div>
}
/>
<Switch>
<Route exact path="/" render={ routeProps =>
<Home
setRedirect={this.setRedirect}
handleUpdate={this.handleUpdate}
{...routeProps} />}
/>
<Route exact path="/definition/:word" render={routeProps =>
<GetWordContainer
setRedirect={this.setRedirect}
handleUpdate={this.handleUpdate}
word={this.state.word}
partOfSpeech={this.state.partOfSpeech}
versions={this.state.versions}
shortdef={this.state.shortdef}
pronunciation={this.state.pronunciation}
{...routeProps} />}
/>
</Switch>
</main>
</>
);
}
}
GetWordContainer.js
class GetWordContainer extends Component {
//this state only updates once
state = {
word: this.props.word,
info: this.props.info,
partOfSpeech: this.props.parOfSpeech,
versions: this.props.versions,
shortdef: this.props.shortdef,
pronunciation: this.props.pronunciation,
}
render (){
return (
<div>
<Search
handleUpdate={this.props.handleUpdate}
setRedirect={this.props.setRedirect}
/>
<div>
{this.state.word}
</div>
<div>
{this.state.partOfSpeech}
</div>
<div>
{this.state.versions.map((v, i) => <div key={i}>{v}</div>)}
</div>
<div>
{this.state.pronunciation}
</div>
<div>
{this.state.shortdef}
</div>
</div>
);
}
}
Your constructor lifecycle method runs only once - during the initialisation of the component. If you are expecting new data from parent component, you can re-render your child by using componentDidUpdate()
or getDerivedStateFromProps
.
componentDidUpdate(prevProps) {
if (prevProps.word || this.props.word) {
this.setState({
word
})
}
}
I notice that your child component is not manipulating the props, it is just a display-only container. Why don't you just pass the props and display it directly rather than taking the longest route? Your child component can be a functional component:
const GetWordContainer = (props) => {
return (
<div>
<Search
handleUpdate={props.handleUpdate}
setRedirect={props.setRedirect}
/>
<div>
{props.word}
</div>
<div>
{props.partOfSpeech}
</div>
<div>
{props.versions.map((v, i) => <div key={i}>{v}</div>)}
</div>
<div>
{props.pronunciation}
</div>
<div>
{props.shortdef}
</div>
</div>
);
}