苦苦挣扎于' in react / redux / saga / selector setup

时间:2017-04-20 20:01:49

标签: javascript reactjs redux redux-saga

最近在项目中使用ARc(Atomic React)(这很棒,而且我认为对于最终将成为企业级产品有很多未来的证据),但它只是未来的证据如果我不能错误地将它拼凑在一起,我现在无法理解在我的应用中如何/何时/何地/为何使用选择器。

请仔细阅读:How is state passed to selectors in a react-redux app?这很棒,但我认为需要再看几个例子来实际获得它。

我试图解决的当前问题是获取user对象(可在应用程序范围内访问),并且使用该数据为帐户设置页面创建一个视图友好的状态片段用户可以修改自己的姓名,电子邮件等。我不想使用user商店,因为他们不希望他们改变任何东西,直到他们真正点击提交,但确实想要在redux中维护表单状态。

我加载了我的用户,这是好的(可以通过我想要的不同容器上的道具访问它): 动作:

export const USER_GET_REQUEST = 'USER_GET_REQUEST'
export const USER_GET_REQUEST_SUCCESS = 'USER_GET_REQUEST_SUCCESS'
export const USER_GET_REQUEST_FAILURE = 'USER_GET_REQUEST_FAILURE'

export const getUserRequest = (params, resolve, reject) => ({
  type: USER_GET_REQUEST,
  params,
  resolve,
  reject,
})

export const getUserRequestSuccess = user => ({
  type: USER_GET_REQUEST_SUCCESS,
  user,
})

export const getUserRequestFailure = error => ({
  type: USER_GET_REQUEST_FAILURE,
  error,
})

萨加斯:

import { take, put, call, fork } from 'redux-saga/effects'
import api from 'services/api'
import * as actions from './actions'

export function* readGetUser() {
  try {
    const data = yield call(api.get, '/user')
    yield put(actions.getUserRequestSuccess(data))
  } catch (e) {
    yield put(actions.getUserRequestFailure(e))
  }
}

export function* watchUserGetRequest() {
  while (true) {
    const { params } = yield take(actions.USER_GET_REQUEST)
    yield call(readGetUser, params)
  }
}

export default function* () {
  yield fork(watchUserGetRequest)
}

减速机:

import { initialState } from './selectors'
import { USER_LOGIN_SUCCESS, USER_GET_REQUEST_SUCCESS } from './actions'

export default (state = initialState, action) => {
  switch (action.type) {
    case USER_LOGIN_SUCCESS:
      return state
    case USER_GET_REQUEST_SUCCESS:
      return {
        ...state,
        user: action.user,
      }
    default:
      return state
  }
}

选择器(我的废话代码注释,单行工作,只要使user实际上有用户数据,但是计算数据在哪里可以得到/如何获得。

export const initialState = {
  user: {},
}

export const getUser = (state = initialState) => state.user || initialState.user

// export const getUser = (state = initialState) => {
//   if (state.user) {
//     return Object.assign({}, state, {
//       formData: {
//         firstName: state.user.firstName,
//         lastName: state.user.lastName,
//         email: state.user.email,
//         phone: state.user.phone,
//       },
//     })
//   }
//
//   return initialState.user
// }

代码帮助是惊人的,明确的解释得到我坚定不移的感情和感激+在我的自传中提及。

1 个答案:

答案 0 :(得分:3)

选择器功能可以并且应该在您想要从商店中提取特定数据的任何地方使用。将它们视为"查询您的状态树",有点像对数据库的SQL查询。

它们最常用于mapStateToProps函数中以提取组件所需的数据,但也适用于需要根据商店内容运行条件逻辑的地方(例如thunk action creator或sagas)。如果需要,您甚至可以在减速器中使用它们。

选择器通常使用reselect库创建,该库可以记忆输入。这意味着最终提供的"输出"只有输入实际发生变化时才会运行。一个简单的例子可能是:

import {createSelector} from "reselect";

const selectUser = state => state.user;

const selectUserFirstName = createSelector(
    selectUser,
    user => user.firstName
);

const selectUserLastName = createSelector(
    selectUser,
    user => user.lastName
);

const selectUserFullName = createSelector(
    [selectUserFirstName, selectUserLastName],
    (firstName, lastName) => firstName + " " + lastName
);

在这个例子中," firstName + lastName"只有在两个输入中的一个实际发生了变化时,才会运行选择器。否则,它将返回先前的缓存结果值。这可以用作:

const mapState = (state) => {
    const userFullName = selectUserFullName(state);

    return {userFullName};
}

有关选择器的更多信息,请参阅Redux Techniques#Selectors and NormalizationReact/Redux links list部分。我还在Practical Redux tutorial series中使用了选择器。 (作为相关说明,您可能需要阅读我的链接列表Practical Redux Part 8: Form Draft Data Management部分中的React and Forms或部分文章。)