警告:setState(...):在现有状态转换期间无法更新(例如在`render`或其他组件的构造函数中)

时间:2016-11-06 16:10:50

标签: reactjs redux

在我的react-redux应用程序中,我试图根据某些属性将一组样式应用于组件。但是,当我加载应用程序时,它抱怨:

Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.

这是根减速器:

import letterColor from './LetterColorReducer';

const root_reducer=combineReducers({
    letterColor:letterColor
});


export default root_reducer;

这是LetterColorReducer文件中的reducer函数:

export default function LetterColor(state={ color:'black', fontWeight: 'normal', fontWeight: 900 },action){

  switch(action.type){
  case 'Corrected_Typed':
    return { color:'green', fontWeight: 'normal', fontWeight: 900 };
  case 'Not_Corrected_Typed':
    return { color:'red',fontWeight: 'normal', fontWeight: 900 };
  case 'Active':
    return { color:'black', fontWeight: 'bold', fontWeight: 900 };
  default:
    return { color:'black', fontWeight: 'normal', fontWeight: 900 };
}
}

我注意到,错误来自切换部分。 但我不知道出了什么问题?

更新

组件代码为:

export default class Letter extends Component{

  render(){
    return(<div style={this.props.Styler()}>
                {this.props.value}
          </div>);
  }

}

Styler()只是一个简单的动作,它要求reducer提供合适的样式。 这是Styler()代码:

export default function(){


       console.log('Here is meeeeee');
         return {type:'Style',payload:''}; 
}

这是容器代码:

function mapStateToProps(state){
  return {newTypedLetter:state.newTypedLetter, letterColor:state.letterColor}
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({Styler},dispatch);
}

export default connect(mapStateToProps,mapDispatchToProps)(Letter);

1 个答案:

答案 0 :(得分:2)

首先,你的减速器是错误的。

reducer会传递应用程序处理的所有操作,包括reducer与之无关的操作。

此外,无论reducer返回什么,都将成为从此开始的状态。小心将reducer视为更改应用程序当前状态的方法而不是作为返回值供您使用的某个实用程序函数。

当你说

  

只是一个简单的动作,要求减速器的正确风格

在我看来,你认为调度一个动作只是调用reducer并返回reducer返回的值。

两者都不是真的。调用Styler()不会返回reducer返回的值。 reducer返回的值是reducer管理的全局app状态切片的新状态。

如果你的reducer返回一个新对象,即使有一个未知的动作进入(就像你的reducer一样),那么它会引起一些大的问题。

首先,每次在您的应用中的任何位置调度任何操作时,您的样式都将恢复为默认样式。

其次,因为每次都返回一个新对象,所以对该状态的任何connect都将被重新渲染。同样,这发生在任何行动上,甚至是不相关的行动。

起实施。

从您的代码和评论中,您似乎正在尝试使用reducer作为一个简单的函数来确定如何为组件设置样式。

不要使用减速机。使用一个简单的函数:

function letterColor(state){
  switch(state){
    case 'CORRECTED_TYPED':
      return { color:'green', fontWeight: 'normal' };
    case 'NOT_CORRECTED_TYPED':
      return { color:'red', fontWeight: 'normal' };
    case 'ACTIVE':
      return { color:'black', fontWeight: 'bold' };
    default:
      return { color:'black', fontWeight: 'normal' };
  }
}

以上功能不是减速机。您可以像这样使用它:

export default class Letter extends Component{
  render(){
    return(<div style={letterColor('CORRECTED_TYPED')}>
                {this.props.value}
          </div>);
  }
}

我使用通常的大写字母:

  • 普通函数以小写字母开头并使用camelCase
  • 构造函数以大写字母开头并使用CamelCase
  • 常量和常量字符串完全是大写的并使用下划线

Redux旨在管理状态。状态是您应用中的当前情况。

随着时间的推移状态发生变化。在Redux中,这仅在调度操作时发生。

找出要呈现内容的样式不会改变应用的状态。因此,不应该发出行动。

如果reducer不知道如何处理一个动作,它应该总是返回与它一起调用的状态。

如果reducer不更改状态中对象的属性,则应始终返回相同的对象。如果reducer不改变状态的子对象的属性,那么它应该总是返回原始子对象作为新状态的一部分。

状态指的是您应用中的当前情况。它不应包含您可以通过其他方式找到的任何数据,例如基于该状态中其他数据的计算。这种数据称为“派生数据”。确定要存储哪些数据以及要导出哪些数据的过程称为normalization