在redux reducer中更新状态的正确方法 [英] Right way to update state in redux reducers

查看:371
本文介绍了在redux reducer中更新状态的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是redux和es6语法的新手。我使用官方的redux教程和这个示例制作我的应用程序。

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

下面有JS片段。我的观点 - 在帖子reducer中定义REQUEST_POST_BODY和RECEIVE_POST_BODY个案。
主要难点 - 在商店中查找和更新正确的对象。

There is JS snippet below. My point - to define REQUEST_POST_BODY and RECEIVE_POST_BODY cases in posts reducer. Main difficult - to find and update right object in store.

我尝试使用示例中的代码:

I try to use code from example:

  return Object.assign({}, state, {
    [action.subreddit]: posts(state[action.subreddit], action)
  })

但是它使用了简单的帖子数组。我不需要通过id找到正确的帖子。

But it used simple array of posts. It's not needed to find right post by id.

这里我的代码:

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

  // Reducer for posts store
  export default function posts(state = initialState, action) {
    switch (action.type) {
    case REQUEST_POST_BODY:
      // here I need to set post.isFetching => true
    case RECEIVE_POST_BODY:
      // here I need to set post.isFetching => false and post.body => action.body
    default:
      return state;
    }
  }

  function requestPostBody(id) {
    return {
      type: REQUEST_POST_BODY,
      id
    };
  }

  function receivePostBody(id, body_from_server) {
    return {
      type: RECEIVE_POST_BODY,
      id,
      body: body_from_server
    };
  }

  dispatch(requestPostBody(3));
  dispatch(receivePostBody(3, {id:3, body: 'blablabla'}));


推荐答案

使用数组



如果您更喜欢坚持使用数组,那么您可以编写一个简化器来处理单个 post 对象。

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

您的根减速器将变为:

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

我们只是在列表中的每个帖子上运行新的reducer,以返回更新的数组在这种情况下,唯一ID将确保只更改一个项目。

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.

如果每个项目都有唯一的字符串/数字ID,那么您可以翻转数组并使用对象代替。

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

如果你也很乐意尝试一些ES7语法,你可以启用使用Babel的Object spread运算符并重写对 Object.assign 的调用。

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

如果你不是那么热衷于使用扩展语法,那么它仍然是可以使 Object.assign 更加可口。

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

这篇关于在redux reducer中更新状态的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆