React Redux如何从数组更新对象

时间:2017-06-25 15:16:41

标签: reactjs redux react-redux

我很反应和减少。 我正在尝试使用以下更新reducer中的状态。

  export default function ReducersTodos(state = [], action) {
    switch (action.type) {
      case ADD_TODO:
                state = [...state, {
                        id: state.length? state.length+1: 1,
                        text: action.value,
                        like: 0
                      }]
                 return state
                 break;
      case ADD_LIKE:
              state = state.map(todo => todo.id === action.id ? { ...todo, like: todo.like+1 } : todo)
              return state
              break;
      case DIS_LIKE:
              state = state.map(todo => todo.id === action.id ? { ...todo, like: todo.like-1 } : todo)
              return state
              break;
      default:
        return state
    }
  }

与组件

相同
export class Like extends React.Component {
      constructor(props){
        super(props);
        // This binding is necessary to make `this` work in the callback
        this._handleClickAdd = this._handleClickAdd.bind(this);
        this._handleClickSub = this._handleClickSub.bind(this);
      }

      _handleClickAdd = function(e) {
        e.preventDefault();
        this.props.addLike(this.props.task.id);
      }
      _handleClickSub = function(e) {
        e.preventDefault();
        this.props.disLike(this.props.task.id);
      }
      render() {
          return (
                <div>
                  Like {this.props.task.like}
                  <button className="btn btn-primary" onClick={this._handleClickAdd} {...this.props.task.like}>+</button>
                  <button className="btn btn-danger" onClick={this._handleClickSub} {...this.props.task.like}>-</button>
                </div>
          );
      }
    }
    function mapDispatchToProps(dispatch) {
      return {addLike: bindActionCreators(addLike, dispatch),
              disLike: bindActionCreators(disLike, dispatch)}
    }
    //set props
    const mapStateToProps = (state, ownProps) => ({todos : state.todos});

    Like = connect(mapStateToProps, mapDispatchToProps)(Like)

当我尝试点击likedislike按钮时。 它重新渲染整个列表,UI看起来很奇怪。 有没有办法只更新数组的一部分而不查看整个数组。

GitHub https://github.com/vinaypost/todos

上提供的工作代码

2 个答案:

答案 0 :(得分:2)

哇,这真是太过分了。我克隆你的仓库,安装它,运行它,检查它抽出的日志,设置redux dev工具并检查动作和状态变化,仔细检查mapStateToProps,盯着它希望我&#39;注意到了什么,但我无法弄清楚发生了什么。我可以看到状态正在进入,并且正如你想要的那样改变,但是ui正在翻转。

最终我发现它here,在减速机附近,或mapStateToProps

this.props.todos.reverse().map(todo =>
  <TodoSingleLi key={todo.id} task={todo}/>
)

此处的问题是reverse()。来自mdn

  

reverse方法转换调用数组对象的元素,改变数组,并返回对数组的引用。

基本上,减速器以外的东西正在更新状态,更糟糕的是not doing so immutably,这解释了所遇到的奇怪程度。

幸运的是,这很容易解决:

this.props.todos.slice().reverse().map(todo =>
  <TodoSingleLi key={todo.id} task={todo}/>
)

slice()添加到链中允许数组安全地变异。来自mdn

  

slice不会改变原始数组。它从原始数组返回浅拷贝元素。

谢谢你。很高兴找到一个改变的诚实到善的错误。

答案 1 :(得分:0)

您可以使用redux-auto简化代码。

<强>组件:

import actions from 'redux-auto'

export class Like extends React.Component {

  render() {
      const id = this.props.task.id
      return (
            <div>
              Like {this.props.task.like}
              <button className="btn btn-primary" onClick={()=>actions.todos.like({id})} {...this.props.task.like}>+</button>
              <button className="btn btn-danger" onClick={()=>actions.todos.dislike({id})} {...this.props.task.like}>-</button>
            </div>
      );
  }
}
//set props
const mapStateToProps = (state, ownProps) => ({todos : state.todos});

Like = connect(mapStateToProps)(Like)

<强>减速:

待办事项/ add.js

export default function (todos, payload) {
  return [...todos, {  id: todos.length + 1,
                    text: payload.value,
                    like: 0 }];
}

待办事项/ like.js

export default function (todos, payload) {
  return todos.map(todo => todo.id === payload.id ? { ...todo, like: todo.like+1 } : todo);
}

待办事项/ dislike.js

export default function (todos, payload) {
  return todos.map(todo => todo.id === payload.id ? { ...todo, like: todo.like-1 } : todo);
}
  

了解上述来源。 redux-auto会根据文件结构自动创建操作并将它们连接起来。文件夹名称成为状态属性的名称。文件夹中的文件是要在该州的该部分执行的操作。