Right way to update state in redux reducers

后端 未结 3 711
悲&欢浪女
悲&欢浪女 2020-12-24 14:20

I\'m a newbie in redux and es6 syntax. I make my app with official redux tutorial, and with this example.

There is JS snippet below. My point - to define REQUEST_PO

3条回答
  •  清歌不尽
    2020-12-24 14:32

    With Arrays

    If you'd prefer to stick with arrays, then you can write a reducer that just tackles single post objects.

    export default function reducePost(post, action) {
      if(post.id !== action.id) return post;
    
      switch(action.type) {
      case REQUEST_POST_BODY:
        return Object.assign({}, post, { isFetching: true });
      case RECEIVE_POST_BODY:
        return Object.assign({}, post, { isFetching: false, body: action.body });
      default:
        return post;
    }
    

    Your root reducer would become:

    export default function posts(state = initialState, action) {
      return state.map(post => reducePost(post, action);
    }
    

    We're just running our new reducer over each post in the list, to return an updated array of posts. In this case, the unique id will ensure that only one item will be changed.

    With Objects

    If each item has a unique string/number id, then you can flip your array around and use an object instead.

    const initialState = {
      items: {
        3: {id:3, title: '1984', isFetching:false},
        6: {id:6, title: 'Mouse', isFetching:false}
      };
    }
    

    Then you can simplify your reducer.

    switch (action.type) {
    case REQUEST_POST_BODY:
      let id = action.id;
      return Object.assign({}, state, {
        [id]: Object.assign({}, state[id], { isFetching: true })
      });
    case RECEIVE_POST_BODY:
      let id = action.id;
      return Object.assign({}, state, {
        [id]: Object.assign({}, state[id], {
          isFetching: false,
          body: action.body
        })
      });
    default:
      return state;
    }
    

    If you're happy to experiment with some ES7 syntax too, you can enable the Object spread operator with Babel and rewrite the calls to Object.assign.

    switch (action.type) {
    case REQUEST_POST_BODY:
      let id = action.id;
      return {
        ...state,
        [id]: {...state[id], isFetching: true }
      };
    case RECEIVE_POST_BODY:
      let id = action.id;
      return {
        ...state,
        [id]: {
          ...state[id],
          isFetching: false,
          body: action.body
        }
      };
    default:
      return state;
    }
    

    If you're not so keen on using the spread syntax, then it's still possible to make Object.assign a bit more palatable.

    function $set(...objects) {
      return Object.assign({}, ...objects); 
    }
    case RECEIVE_POST_BODY:
      let id = action.id;
      return $set(state, {
        [id]: $set(state[id], {
          isFetching: false,
          body: action.body
        })
      });
    

提交回复
热议问题