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

时间:2017-05-31 08:03:17

标签: reactjs react-native

错误讯息:

  

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

这是一个反应原生的应用程序,但我认为,这更像是一个反应问题。

我收到了标题中描述的错误。但我对原因感到困惑,我没有在任何父组件或子组件中设置状态。所以我有一个孙子组件(CardLayoutResult),它呈现一个listView,每行呈现一个新组件(Render row),它有一个click事件,点击它时会调用一个函数(onselectLayout)来自props(从父组件传递)组件)(父函数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>
  );
}

Grand Child Component

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函数

中设置状态时

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

我想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>
  )   

答案 2 :(得分:0)

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

在此代码段中

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

在将函数作为prop本身传递时,你正在调用函数,所以每次组件渲染时都会设置状态,这很好。

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

要解决此问题,只需将父项中的函数作为setCardTemplate: this.setCardTemplate传递即可。它将仅在行按下时设置状态(并在内部调用渲染),而不是每次渲染时都设置