在 react/redux/saga/selector 设置中与 'what goes where' 斗争

Struggling with 'what goes where' in react/redux/saga/selector setup

在一个项目中新使用 ARc(Atomic React)(这很棒,我认为对于最终将成为企业级产品的东西有大量的未来证明),但它只是未来的证明,如果我不要把它拼错了,我目前无法理解 how/when/where/why 在我的应用程序中使用选择器。

已阅读: 很棒,但我认为需要再看几个例子才能真正理解它。

我目前要解决的问题是获取一个 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 实际上拥有用户数据,但是计算数据在哪里 GO/HOW 它到达那里。

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

代码帮助很棒,清晰的解释让我坚定不移的爱和感激+在我的自传中提到。

选择器函数可以而且应该用在任何您想从商店中提取特定数据的地方。将它们视为 "queries into your state tree",有点像对数据库的 SQL 查询。

它们最常用于您的 mapStateToProps 函数中以提取组件所需的数据,但也用于您需要 运行 基于存储内容的条件逻辑的地方(例如 thunk 动作创建者或传奇)。如果需要,您甚至可以在减速器中使用它们。

选择器通常是使用 reselect 库创建的,它会记忆输入。这意味着如果输入实际发生变化,最终提供的 "output" 函数只会 运行 。一个简单的例子可能是:

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" 选择器仅会 运行 如果两个输入之一实际已更改。否则,它将 return 先前缓存的结果值。这可能会用作:

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

    return {userFullName};
}

有关选择器的更多信息,请参阅我的链接列表的 Redux Techniques#Selectors and Normalization section of my React/Redux links list. I also make use of selectors in my Practical Redux tutorial series. (As a related note, you may want to read Practical Redux Part 8: Form Draft Data Management, or some of the articles in the React and Forms 部分。)