为啥不能根据道具反应设置初始状态

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”钩子中一遍又一遍地设置初始状态

更新道具时反应本机组件不透明度不更新

ReactJs:在使用动态 Taglist 时使用道具设置初始状态

为啥我不能将此信息从一个反应组件推送到另一个?

即使道具没有改变,为啥还要对重新渲染组件做出反应?