Why cant react set initial state based on props
Solution 1
Initializing the state from the props in the constructor, or as a class property, will not update the state when the prop changes. However, react does detect the prop change, and rerenders the component.
Example:
class AttachStateToProps extends React.Component {
state = {
stateValue: this.props.VALUE,
}
render() {
console.log('Value of Prop - ', this.props.VALUE)
console.log('Value of State - ', this.state.stateValue)
return null
}
}
const renderWithVal = (val) => ReactDOM.render(
<AttachStateToProps VALUE={val} />,
demo
);
renderWithVal(5);
renderWithVal(15);
renderWithVal(115);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>
To update the state when the prop changes, you need to use a component's lifecycle method.
With React ^16.3 you can use the static getDerivedStateFromProps()
method to update the state from the props (and initialize it as well):
static getDerivedStateFromProps(nextProps) {
return {
stateValue: nextProps.VALUE,
}
}
class AttachStateToProps extends React.Component {
state = {};
static getDerivedStateFromProps(nextProps) {
return {
stateValue: nextProps.VALUE,
}
}
render() {
console.log('Value of Prop - ', this.props.VALUE)
console.log('Value of State - ', this.state.stateValue)
return null
}
}
const renderWithVal = (val) => ReactDOM.render(
<AttachStateToProps VALUE={val} />,
demo
);
renderWithVal(5);
renderWithVal(15);
renderWithVal(115);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>
With React versions prior to 16.3, you can use componentWillReceiveProps()
.
Note: componentWillReceiveProps is deprecated, but will work 'till version 17.
componentWillReceiveProps(nextProps, prevState) {
this.setState({
stateValue: nextProps.VALUE,
})
}
Solution 2
It will not work without super(props) in constructor.
class AttachStateToProps extends React.Component {
constructor(props) {
super(props);
this.state = { stateValue: this.props.VALUE,
}
}
render() {
console.log('Value of Prop - ', this.props.VALUE) console.log('Value of State - ', this.state.stateValue) return null
}
}
q3e
Almost expert JS dev with competent frontend skills using ReactJS
Updated on June 09, 2022Comments
-
q3e almost 2 years
I have a es6 react component that I want the initial value of the state to depend on that of the passed down prop, but its value is always false:
AttachStateToProps component
<AttachStateToProps VALUE=false />
AttachStateToProps component:
class AttachStateToProps extends React.Component { state = { stateValue: this.props.VALUE, } render() { console.log('Value of Prop - ', this.props.VALUE) console.log('Value of State - ', this.state.stateValue) return null } }
Every time the value of the prop VALUE is changed, I get:
`Value of Prop - false` // this changes whenever I change prop value in <AttachStateToProps />
and
`Value of State - false` // this does not change accordingly.
I figure it could be something to do with state/setState being async and older
getinitialState
but I don't get why it.