假设我有以下内容:

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return {
    type: SOME_ACTION,
  }
}

在那个动作创建器中,我想访问全局存储状态(所有还原器)。这样做更好吗:

import store from '../store';

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return {
    type: SOME_ACTION,
    items: store.getState().otherReducer.items,
  }
}

或:

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return (dispatch, getState) => {
    const {items} = getState().otherReducer;

    dispatch(anotherAction(items));
  }
}

当前回答

I wouldn't access state in the Action Creator. I would use mapStateToProps() and import the entire state object and import a combinedReducer file (or import * from './reducers';) in the component the Action Creator is eventually going to. Then use destructuring in the component to use whatever you need from the state prop. If the Action Creator is passing the state onto a Reducer for the given TYPE, you don't need to mention state because the reducer has access to everything that is currently set in state. Your example is not updating anything. I would only use the Action Creator to pass along state from its parameters.

在减速器中执行如下操作:

const state = this.state;
const apple = this.state.apples;

如果你需要对你所引用的TYPE的状态执行操作,请在减速器中执行。

如果我说错了请指正!!

其他回答

对于在动作创建者中访问状态是否是一个好主意,有不同的意见:

Redux creator Dan Abramov feels that it should be limited: "The few use cases where I think it’s acceptable is for checking cached data before you make a request, or for checking whether you are authenticated (in other words, doing a conditional dispatch). I think that passing data such as state.something.items in an action creator is definitely an anti-pattern and is discouraged because it obscured the change history: if there is a bug and items are incorrect, it is hard to trace where those incorrect values come from because they are already part of the action, rather than directly computed by a reducer in response to an action. So do this with care." Current Redux maintainer Mark Erikson says it's fine and even encouraged to use getState in thunks - that's why it exists. He discusses the pros and cons of accessing state in action creators in his blog post Idiomatic Redux: Thoughts on Thunks, Sagas, Abstraction, and Reusability.

如果您发现您需要这样做,那么您建议的两种方法都可以。第一种方法不需要任何中间件:

import store from '../store';

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return {
    type: SOME_ACTION,
    items: store.getState().otherReducer.items,
  }
}

然而,你可以看到它依赖于从某个模块导出的单例存储。我们不建议这样做,因为这样会使在应用程序中添加服务器渲染变得更加困难,因为在大多数情况下,在服务器上,每个请求都需要一个单独的存储。因此,虽然从技术上讲这种方法是可行的,但我们不建议从模块中导出存储。

这就是为什么我们推荐第二种方法:

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return (dispatch, getState) => {
    const {items} = getState().otherReducer;

    dispatch(anotherAction(items));
  }
}

这需要你使用Redux坦克中间件,但它在客户端和服务器上都工作得很好。你可以阅读更多关于Redux坦克和为什么它在这种情况下是必要的在这里。

理想情况下,您的操作不应该“臃肿”,并且应该包含尽可能少的信息,但是您应该在自己的应用程序中自由地执行最适合自己的操作。Redux常见问题解答中有关于拆分操作创建者和还原器之间逻辑的信息,以及在操作创建者中使用getState可能有用的时间。

I wouldn't access state in the Action Creator. I would use mapStateToProps() and import the entire state object and import a combinedReducer file (or import * from './reducers';) in the component the Action Creator is eventually going to. Then use destructuring in the component to use whatever you need from the state prop. If the Action Creator is passing the state onto a Reducer for the given TYPE, you don't need to mention state because the reducer has access to everything that is currently set in state. Your example is not updating anything. I would only use the Action Creator to pass along state from its parameters.

在减速器中执行如下操作:

const state = this.state;
const apple = this.state.apples;

如果你需要对你所引用的TYPE的状态执行操作,请在减速器中执行。

如果我说错了请指正!!

我想建议另一个我认为最干净的替代方案,但它需要react-redux或类似的东西-同时我还使用了其他一些奇特的功能:

// actions.js
export const someAction = (items) => ({
    type: 'SOME_ACTION',
    payload: {items},
});
// Component.jsx
import {connect} from "react-redux";

const Component = ({boundSomeAction}) => (<div
    onClick={boundSomeAction}
/>);

const mapState = ({otherReducer: {items}}) => ({
    items,
});

const mapDispatch = (dispatch) => bindActionCreators({
    someAction,
}, dispatch);

const mergeProps = (mappedState, mappedDispatches) => {
    // you can only use what gets returned here, so you dont have access to `items` and 
    // `someAction` anymore
    return {
        boundSomeAction: () => mappedDispatches.someAction(mappedState.items),
    }
});

export const ConnectedComponent = connect(mapState, mapDispatch, mergeProps)(Component);
// (with  other mapped state or dispatches) Component.jsx
import {connect} from "react-redux";

const Component = ({boundSomeAction, otherAction, otherMappedState}) => (<div
    onClick={boundSomeAction}
    onSomeOtherEvent={otherAction}
>
    {JSON.stringify(otherMappedState)}
</div>);

const mapState = ({otherReducer: {items}, otherMappedState}) => ({
    items,
    otherMappedState,
});

const mapDispatch = (dispatch) => bindActionCreators({
    someAction,
    otherAction,
}, dispatch);

const mergeProps = (mappedState, mappedDispatches) => {
    const {items, ...remainingMappedState} = mappedState;
    const {someAction, ...remainingMappedDispatch} = mappedDispatch;
    // you can only use what gets returned here, so you dont have access to `items` and 
    // `someAction` anymore
    return {
        boundSomeAction: () => someAction(items),
        ...remainingMappedState,
        ...remainingMappedDispatch,
    }
});

export const ConnectedComponent = connect(mapState, mapDispatch, mergeProps)(Component);

如果你想重用它,你必须将特定的mapState、mapDispatch和mergeProps提取到函数中,以便在其他地方重用,但这使得依赖关系非常清楚。

当您的场景很简单时,您可以使用

import store from '../store';

export const SOME_ACTION = 'SOME_ACTION';
export function someAction() {
  return {
    type: SOME_ACTION,
    items: store.getState().otherReducer.items,
  }
}

但有时你的动作创建者需要触发多个动作

例如异步请求,所以你需要 请求加载请求加载成功请求加载失败动作

export const [REQUEST_LOAD, REQUEST_LOAD_SUCCESS, REQUEST_LOAD_FAIL] = [`REQUEST_LOAD`
    `REQUEST_LOAD_SUCCESS`
    `REQUEST_LOAD_FAIL`
]
export function someAction() {
    return (dispatch, getState) => {
        const {
            items
        } = getState().otherReducer;
        dispatch({
            type: REQUEST_LOAD,
            loading: true
        });
        $.ajax('url', {
            success: (data) => {
                dispatch({
                    type: REQUEST_LOAD_SUCCESS,
                    loading: false,
                    data: data
                });
            },
            error: (error) => {
                dispatch({
                    type: REQUEST_LOAD_FAIL,
                    loading: false,
                    error: error
                });
            }
        })
    }
}

注意:你需要redux-thunk在动作创建器中返回函数

我同意@Bloomca。将存储所需的值作为参数传递给分派函数似乎比导出存储简单。我举个例子:

import React from "react";
import {connect} from "react-redux";
import * as actions from '../actions';

class App extends React.Component {

  handleClick(){
    const data = this.props.someStateObject.data;
    this.props.someDispatchFunction(data);
  }

  render(){
    return (
      <div>       
      <div onClick={ this.handleClick.bind(this)}>Click Me!</div>      
      </div>
    );
  }
}


const mapStateToProps = (state) => {
  return { someStateObject: state.someStateObject };
};

const mapDispatchToProps = (dispatch) => {
  return {
    someDispatchFunction:(data) => { dispatch(actions.someDispatchFunction(data))},

  };
}


export default connect(mapStateToProps, mapDispatchToProps)(App);