【问题标题】:React: Warning setState Cannot update during an existing state transition (such as within a render)React:警告 setState 在现有状态转换期间无法更新(例如在渲染中)
【发布时间】:2017-10-31 22:01:58
【问题描述】:

错误信息:

React:警告 setState 在现有状态期间无法更新 过渡(例如在渲染中)

这是一个 react-native 应用程序,但我认为,这更像是一个 react 问题。

我收到标题中描述的错误。但我对原因感到困惑,我没有在任何父组件或子组件中设置状态。所以我有一个孙子组件(CardLayoutResult),它呈现一个listView,每一行呈现一个新组件(Render row),它有一个点击事件,点击它从props调用一个函数(onselectLayout)(从父组件传递(个性化组件)(父函数setCardTemplate)。然后这个父函数调用父内部状态的setState。然后发生重新渲染。

为什么点击后会出现这个错误?

父组件

export class Personalization extends Component {

constructor(props) {
 super(props);

 this.state = {
   showModel: true,
   editorState: {}
 };

  this.setCardTemplate = this.setCardTemplate.bind(this);
}

setCardTemplate(selectedTemplateObj){
  console.log(JSON.stringify(selectedTemplateObj));
  this.setState({
    showModel: false,
    editorState: selectedTemplateObj
  });
}

render() {
  return (
   <View>
     <CreateCardStep containerState={{showModel:this.state.showModel ,
              editorState: this.state.editorState 
              setCardTemplate:this.setCardTemplate}} />
   </View>
  )
}

子组件

const CreateCardStep = (_props)  => {
  return (
    <View>
       <CardLayoutResults containerState={_props.containerState} />
    </View>
  );
}

大子组件

export class CardLayoutResults extends Component {
  constructor(props) {
      super(props);
  }
  render() {

   return(

    <View>
      <ListView
        RenderRow = {(data) => <RenderRow styles={styles} rowObj={data} onSelectLayout={this.props.containerState.setCardTemplate} /> } 
    </View>    
   )
  }

渲染行

 const RenderRow = (props) => {
  let base64Image = 'data:image/png;base64,'.concat(props.rowObj.base);

 return (
 <View style={props.styles.templateImage}>
   <TouchableHighlight onPress={() => props.onSelectLayout(props.rowObj)}>
     <Image style={props.styles.thumbnail} resizeMode= {Image.resizeMode.contain} source={{uri: base64Image}}/>
   </TouchableHighlight>
 </View>
 );
};

- 更新 这个问题似乎是在 setCardTemplate 函数中设置状态时出现的

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    问题在于您将 props 从父组件传递给子组件的方式。

    在这个sn-p中

     <CreateCardStep containerState={{showModel:this.state.showModel ,
              editorState: this.state.editorState 
              setCardTemplate:(val) => this.setCardTemplate(val)}} />
    

    在将函数作为道具本身传递时,您正在调用该函数,因此每次渲染组件时都会设置状态,这很好。

    但是,当您单击 Render Row 组件状态时,在完成渲染周期之前尚未为同一属性设置导致此警告的状态。

    要修复它,只需将父函数作为setCardTemplate: this.setCardTemplate 传递。它只会在按行时设置状态(并在内部调用渲染),而不是每次渲染时

    【讨论】:

      【解决方案2】:

      我猜 listView 的 renderRow 调用不正确

      试试

      <View>
        <ListView
          renderRow = {(data) => <RenderRow rowObj={data} onSelectLayout={this.props.containerState.setCardTemplate} />} 
         />
      </View>
      

      并从个性化组件中传递道具,例如

      return (
         <View>
           <CreateCardStep containerState={{showModel:this.state.showModel ,
                    editorState: this.state.editorState 
                    setCardTemplate:(val) => this.setCardTemplate(val)}} />
         </View>
        )   
      

      【讨论】:

      • 运气不好。我相信这一定与反应渲染生命周期有关
      【解决方案3】:

      您要么需要在构造函数中绑定 setCardTemplate 函数,要么从 lambda 函数中调用它(绑定更好)

      <View>
            <ListView renderRow = {(data => rowObj={data}} onSelectLayout={() => this.props.containerState.setCardTemplate} />
      </View>
      

      【讨论】:

      • 对不起,我已经有了这个绑定。我刚刚编辑了我的帖子。
      • &lt;/view&gt; 结束标签是小写的,在 CardLayoutResults 组件中应该是大写。而 RenderRow 道具应该是 renderRow.
      • 另外,onSelectLayout 不应该在 renderRow 道具中,而应该在独立道具中。
      • renderRow= {(data) => } /> 不走运。我的父函数 setCardTemplate 正在被调用。没有 setState(在 setCardTemplate 函数中)它工作正常。问题是在该函数中设置状态时
      猜你喜欢
      • 2017-12-20
      • 2017-05-16
      • 2016-09-20
      • 2017-02-22
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      相关资源
      最近更新 更多