如何更新reducer的状态?

How to update the state of reducer?

我正在传递要更新状态的 posts 数组中对象的索引 (id)。我可以使用 findIndex 找到元素的索引并更改 number 键。我不知道如何将更新后的 object 传递回 state/array。

我的减速器:

const initialState = {
    posts: [
      {id:1, name:'post1', number:11},
      {id:2, name:'post2', number:22},
      {id:3, name:'post3', number:33}
   ]
}

export default function newData (state = initialState, action) {

  switch (action.type) {

    case "updateNumber": {

   // find object to update
    const index = state.posts.findIndex(({ id }) => id === action.payload);

    if (index > -1 ) {
      const toIncrement = state.posts[index];
      const number = toIncrement.number++;

      // create new object with existing data and newly incremented number
      const updatedData = { ...toIncrement, number };

      // return new array that replaces old object with incremented object at index
     // the state is not getting updated with the following:

      return [...state.posts.slice(0, index), updatedData, ...state.posts.slice(index + 1)];

    }

      // return state if no object is found
      return state;
    }

  default:
    return state
  }
}

我做错了什么?还有其他更新状态的方法吗?请帮忙。

我认为您正在改变 redux 中不允许的 state
尝试更改此设置:

if (index > -1 ) {
      const toIncrement = state.posts[index];
      const number = toIncrement.posts.number++;  

为此:

if (index > -1 ) {
      const toIncrement = {...state.posts[index]};
      const number = toIncrement.posts.number + 1;

顺便说一下,请确保 posts.number 确实是一个数字而不是字符串。

更新
您的初始状态是一个对象,但当您更改状态时,您的 reducer 返回一个数组。
将您的减速器更改为:

(state = initialState, action) => {
  switch (action.type) {
    case "updateNumber": {
      // find object to update
      const index = state.posts.findIndex(({ id }) => id === action.payload);
      if (index > -1) {
        const toIncrement = state.posts[index];
        const number = toIncrement.number + 1; // don't mutate the object with ++

        // create new object with existing data and newly incremented number
        const updatedData = { ...toIncrement, number };

        // return new array that replaces old object with incremented object at index
        // the state is not getting updated with the following:
        return { // this should be an object with a key of posts
          posts: [
          ...state.posts.slice(0, index),
          updatedData,
          ...state.posts.slice(index + 1)
        ]};
      }

      // return state if no object is found
      return state;
    }

    default:
      return state;
  }
};

这是您的代码的一个工作示例:

const {createStore} = Redux;


const initialState = {
  posts: [
    { id: 1, name: "post1", number: 11 },
    { id: 2, name: "post2", number: 22 },
    { id: 3, name: "post3", number: 33 }
  ]
};

const newData = (state = initialState, action) => {
  switch (action.type) {
    case "updateNumber": {
      // find object to update
      const index = state.posts.findIndex(({ id }) => id === Number(action.payload));
      if (index > -1) {
        const toIncrement = state.posts[index];
        const number = toIncrement.number + 1;

        // create new object with existing data and newly incremented number
        const updatedData = { ...toIncrement, number };

        // return new array that replaces old object with incremented object at index
        // the state is not getting updated with the following:
        return {
          posts: [
            ...state.posts.slice(0, index),
            updatedData,
            ...state.posts.slice(index + 1)
          ]
        };
      }

      // return state if no object is found
      return state;
    }

    default:
      return state;
  }
};

const store = createStore(newData);

const Posts = ({ data }) => {
  //debugger
  return (
    <ul>
      {data.posts.map(post => (
        <li>{`Number - ${post.number} | Id - ${post.id}`}</li>
      ))}
    </ul>
  );
};

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentId: 1
    };
  }

  handleInputChange = e => this.setState({ currentId: e.target.value });

  onClick = () => {
    const { currentId } = this.state;
    store.dispatch({ type: "updateNumber", payload: currentId });
  };

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.currentId}
          onChange={this.handleInputChange}
        />
        <button onClick={this.onClick}>Change By Id</button>

        <Posts data={this.props.data} />
      </div>
    );
  }
}
const render = () => {
  ReactDOM.render(
    <App data={store.getState()} />,
    document.getElementById("root")
  );
};
render();
store.subscribe(render);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.min.js"></script>
<div id="root"></div>