如何更新减速机的状态?

时间:2017-10-01 18:59:26

标签: reactjs react-native ecmascript-6 redux react-redux

我将id数组中对象的索引(posts)传递给要更新的状态。我能够找到findIndex元素的索引并更改number键。我无法弄清楚如何将更新的object传递回状态/数组。

我的减速机:

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
  }
}

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

1 个答案:

答案 0 :(得分:3)

我认为你正在改变state中不允许的redux 尝试更改此内容:

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>