我正在使用Redux构建一个应用程序,我遇到了这个问题:当我向其添加元素时,我的reducer的状态会更新,但显示保持不变。
以下是我的组件的代码:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { displayList } from '../actions';
import { bindActionCreators } from 'redux';
class ListDisplayer extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="container">
<form>
<div className="field is-grouped">
<div className="control">
<button className="button is-primary"
onClick={(e) => {e.preventDefault();this.props.dispatch(displayList())}}>
Display
</button><br/>
List
{
this.props.list.map((item,index) =>
<p key={index}>{item}</p>
)
}
</div>
</div>
</form>
</div>
)
}
}
function mapStateToProps(state){
return {
list: state.displayReducer,
};
}
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators(displayList, dispatch) }
}
export default connect(mapStateToProps)(ListDisplayer);
要测试问题是否来自reducer,我会这样初始化:
import * as actionType from '../actions/ActionType';
const displayReducer = (state = ['haha','haha','haha'], action) => {
let newState;
switch (action.type) {
case actionType.DISPLAY_LIST:
let newarr = state;
newarr.push(action.payload);
console.log(newarr);
return newState = newarr;
default:
return state
}
}
export default displayReducer;
但是,当我单击Display按钮并执行displayList()函数(参见组件代码)时,如控制台所示,reducer的状态会更新:
但是,屏幕上仍然只有三个'哈哈',这意味着我的mapStateToProps无法正常工作,或者我没有在reducer中正确更新状态。我已经在本网站和GitHub上看到了类似的错误,但这些解决方案都不适用于我。
答案 0 :(得分:3)
引自Redux&#39;文档
为什么我的组件没有重新渲染,或者我的mapStateToProps正在运行? 直接意外地改变或修改你的国家是迄今为止 组件在动作之后不重新渲染的最常见原因 被派遣
有关详细信息,请访问website
基本上,以下代码片段
let newarr = state;
newarr.push(action.payload);
console.log(newarr);
改变原始状态
为什么呢?因为
1)Array.push()方法改变原始数组(并返回新数组的长度)
2)在Javascript中,当变量引用一个对象(包括数组)时,&#34;值&#34;是对对象的引用。这意味着,每当你执行newarr.push(newItem)时,如果你控制日志(状态),你可以看到,同样的项目也包含在状态本身中。但事实并非如此。
为了防止意外突变,您应该执行以下操作,
let newarr = [...state, action.payload]
使用spread运算符,您可以使用state数组中的值,在逗号之后,还会引入一个新值,该值将作为新项添加。
多亏了这种方式,您不必使用newarr.push()
方法并改变数组,而是创建一个新数组,复制旧状态的值并在此期间引入新值这个复制过程
总而言之,您可以尝试更新代码吗
const displayReducer = (state = ['haha','haha','haha'], action) => {
let newState; // you don't need this, you can get delete this line
switch (action.type) {
case actionType.DISPLAY_LIST:
return [...state, action.payload] // return a new array that copies the original state's values and introduces a new value during this process
default:
return state
}
}
答案 1 :(得分:1)
您的reducer
必须是纯函数,因此请勿使用push
方法。
case actionType.DISPLAY_LIST:
return [...state, ...action.payload]