为啥不能根据道具反应设置初始状态
Posted
技术标签:
【中文标题】为啥不能根据道具反应设置初始状态【英文标题】:Why cant react set initial state based on props为什么不能根据道具反应设置初始状态 【发布时间】:2018-10-28 10:40:42 【问题描述】:我有一个 es6 react 组件,我希望 state 的初始值依赖于传递的 prop 的初始值,但它的值始终为 false:
AttachStateToProps 组件
<AttachStateToProps VALUE=false />
AttachStateToProps 组件:
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
每次更改道具VALUE的值时,我都会得到:
`Value of Prop - false` // this changes whenever I change prop value in
<AttachStateToProps />
和
`Value of State - false` // this does not change accordingly.
我认为是 it could be something to do with state/setState being async 和更老的 getinitialState
,但我不明白为什么。
【问题讨论】:
尝试改变componentDidMount中的状态 现在它一直返回true
。 eslint 也抱怨 [eslint] Do not use setState in componentDidMount (react/no-did-mount-set-state)
- 我认为这不是一个好的模式
【参考方案1】:
从构造函数中的 props 初始化状态,或作为类属性,不会在 prop 更改时更新状态。但是,react 确实会检测到 prop 更改,并重新渲染组件。
示例:
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>
要在prop改变时更新状态,需要使用组件的lifecycle method。
使用 React ^16.3,您可以使用静态 getDerivedStateFromProps()
方法从 props 更新状态(并初始化它):
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>
对于 16.3 之前的 React 版本,您可以使用 componentWillReceiveProps()
。
注意:componentWillReceiveProps 已被弃用,但将在版本 17 之前有效。
componentWillReceiveProps(nextProps, prevState)
this.setState(
stateValue: nextProps.VALUE,
)
【讨论】:
【参考方案2】:如果没有构造函数中的 super(props),它将无法工作。
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
【讨论】:
以上是关于为啥不能根据道具反应设置初始状态的主要内容,如果未能解决你的问题,请参考以下文章
为啥在反应的“useState”钩子中一遍又一遍地设置初始状态