用 Redux 更新整个状态的方法是什么?

What's the way to update the whole state with Redux?

我有一个空的 state 对象,它在应用程序启动时使用默认的空字段进行实例化。

它包含一个名为 users 的空数组。

const state = {
                  users: []
              }

开始时,我向服务器发送一些命令,然后服务器发送数据作为响应。

因为我需要填充 users,我想我只想用从服务器接收到的新数组替换整个用户数组。

我读到,在 redux 中,你采用当前状态,对其应用一些更改,然后 return 一个新状态。当我想更改用户密码时听起来不错,然后我会调用这样的操作:

{
    action: 'CHANGE_PASSWORD',
    user: 'john',
    password: 'karamba',
}

它将由调度程序管理,其中将在当前状态下找到用户 john,密码将替换为新密码。

但这对于我想要加载一些初始数据的场景是否正确?

如果是这样,动作会是什么样子?

{
    action: 'FETCH_USERS'
}

然后 reducer 会替换整个 users 数组?

你的 reducer 应该替换 props 里面的 users。然后在 componentWillReceiveProps 方法中更改本地 state 并从使用的道具 this.setState{users: @nextProps.users}

设置本地状态

如果您需要在应用程序启动时设置状态,请查看 store and createStore 的工作原理。当您传递 preloadedState 属性时,它会将其传递给您的减速器。

如果您在应用程序执行期间更改 users 数组,使用 AJAX 调用或类似的东西,您可以使用操作来完成它。

因此,您可以发送一个 REQUEST_USERS 操作。此操作将向您的服务器发送一个 AJAX 请求,并且在此请求的成功和错误回调中,您可以调度 REQUEST_USERS_SUCCESSREQUEST_USERS_FAILURE 操作,有效负载是新用户或一条错误消息。

查看 here 了解更多关于如何使用 redux 正确处理 AJAX 请求的信息。

让我们先介绍一些基础知识

  • 应用程序中的所有状态更改都存储在单个对象状态树中。
  • 这个状态树需要是不可变的。
  • 任何时候你需要更新(替换)你需要发送一个动作的状态,这个动作事件必须被一个 reducer 捕获来替换你的状态。
  • 动作是平面 JS 对象,描述了对 state/app 的最小更改。它必须有一个类型 属性.
  • UI 组件本身并不知道更改是如何完成的。他们只知道他们需要派发一个动作。
  • 纯函数 - Return 值仅取决于参数的值,没有副作用(网络或数据库调用),幂等(相同的参数总是可预测性 return 相同的值), 他们不修改传递给他们的值
  • Reducer - 是一个纯函数,它获取应用程序的整个状态和操作以及 return 应用程序的下一个状态(确保不修改当前状态,它必须 return 一个新对象)并具有以下方法签名:(State,Action) => State;

那么对于异步流(您从网络请求中检索数据),您的操作是什么样的?当您使用异步流时需要使用某种类型的中间件 http://redux.js.org/docs/advanced/Middleware.html.

在下面的操作中,我使用了一个名为 thunk 的中间件。

actions.js:

export function receiveAllProducts(users){
    return {
        type: 'RECEIVED_ALL_USERS',
        users: users
    }
}


export function fetchALLUserData(){
    return thunkLoadAllUserData;
}


const thunkLoadAllUserData = (dispatch) => {
        let users = [];
        users = //Some network request to get data
        dispatch(receivedAllUserData(users));
    });
}

所以你会向 fetchALLUserData 发送一个动作,return 是一个 thunk 函数(用于异步流的 redux 中间件)来检索用户,然后调用 receivedAllUserData 作为类型的操作:'RECEIVED_ALL_USERS'。这种类型是由你的减速器捕获的,它使用一个纯函数和 Object.assign 到 return 一个新状态(与新用户)。

reducer 纯函数是什么样子的? reducers.js:

const initialState = {}

export default (currentState = initialState, action = {}) => {


  switch (action.type) {

    case 'RECEIVED_ALL_USERS':
      return Object.assign({}, currentState, {
        users: action.users,
      });
    case 'RECEIVE_ALL_PRODUCTS':
      return Object.assign({}, currentState, {
        productsAsObject: action.productsObject,
      });

    // ...other actions

    default:
      return currentState;
  }
}

Object.assign()方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。 因此将复制整个 currentState 并用获取的用户覆盖您的用户属性

或者你也可以使用对象展开运算符来更新状态:http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html