Redux 动作中的 Getters - React Native

Getters in Redux's actions - React Native

我希望有一些函数可以获取当前状态来用它做一些逻辑,而不必通过参数将当前状态传递给函数。

这是我的例子。

在我的操作文件中,我有:

export const addToSearchHistory = (newSearch) => ({type: ADD_TO_SEARCH_HISTORY, newSearch})
export const addToCardHistory = (newCard) => ({type: ADD_TO_CARD_HISTORY, newCard})

例如,我想要一个 "getter" 函数来告诉我 "Search history" 是否命中了 10 个项目。所以我所做的是:

export const searchHasMaxHistory = () => (dispatch, getState) => {
  var state = getState()
      search = state.search

  return search.history == 10 ? true : false
}

然后我使用 bindActionCreators 将此函数与其他 "real" 操作绑定:

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    addToSearchHistory,
    addToCardHistory,

    searchHasMaxHistory
  }, dispatch)
} 

所以我可以像任何正常操作一样访问。它运行良好,完全符合我的要求。

但真正的问题是,将它像一个动作一样绑定但它不是 return 一个动作是否是反模式?我可以 运行 这样做吗?有 "right" 解决方案吗?

我看到你的目标是:

I would like to have functions that can get the current state to do some logic with it, without having to pass the current state via parameters to the function.

但是bindActionCreators(actionCreators, dispatch)是另外一个目的。

它用 dispatch 调用包装所有动作创建者,因此可以直接调用它们。

我们以一种 hackish 的方式做事,而不是我们为什么不使用原始的 store 对象来获取状态。

为您的 store 对象创建一个 getter createStore

import { createStore } from 'redux'
import reducer from './reducer';

let store = {};

export default function storeCreator () {
    // ...do things

    store = createStore(reducer);

    // ...do more things

    return store;  
}

export function getStore() {
    return store;
}

现在在你的 state-getter:

import { getStore } from './storeCreator';

export function searchHasMaxHistory() {
  const store = getStore();
  const state = store.getState();
  const search = state.search;

  return search.history == 10 ? true : false
}

看看connect()

docs

mapStateToProps(state): (Function): If specified, the component will subscribe to Redux store updates. Any time it updates, mapStateToProps will be called

所以你可以这样写你的 connect() 子句:

function mapStateToProps(state) {
  return {
    searchHasMaxHistory: state.search.history === 10
  };
}
connect(mapStateToProps)(YourComponent)

但是,当然,这会在每次商店更改时计算您的新价值。你可能不想要那样。在那种情况下,您可以定义一个单独的函数,并在每次商店(状态)更改时将您的状态绑定到它。

function isMaxHistoryReached(state) {
  return state.search.history === 10;
}

function mapStateToProps(state) {
  return {
    searchHasMaxHistory: isMaxHistoryReached.bind(YourComponent, state)
  };
}
connect(mapStateToProps)(YourComponent)

现在仍然会在每次状态更改时在内存中创建一个新函数,但不会调用它。

为此,您应该通过 mapStateToProps 函数将 "getter"(在 the docs 中描述为 "selector")绑定到您的组件。

// the selector (probably in your reducer file)

export const searchHasMaxHistory = state => {
  return state.search.history == 10 ? true : false
}

// in your component

const mapStateToProps = (state) => {
  return {
    hasHitMaxHistory: searchHasMaxHistory(state)
  }
}

const mapDispatchToProps = ... // keep the same, remove your "getter"

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(YourComponent)

这种方法对我来说更有意义,因为您的组件的新属性将按预期运行,并在返回值更改时触发 render()。