如何使用 connect w/Redux 从 this.props 获得简单的调度?

How to get simple dispatch from this.props using connect w/ Redux?

我连接了一个简单的 React 组件(映射一个简单的 array/state )。为了避免引用商店的上下文,我想要一种直接从道具中获取 "dispatch" 的方法。我见过其他人使用这种方法,但由于某种原因无法访问它:)

这是我目前使用的每个 npm 依赖项的版本

"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"

这是带有连接方法的组件

class Users extends React.Component {
    render() {
        const { people } = this.props;
        return (
            <div>
                <div>{this.props.children}</div>
                <button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
            </div>
        );
    }
};

function mapStateToProps(state) {
    return { people: state.people };
}

export default connect(mapStateToProps, {
    fetchUsers
})(Users);

如果您需要查看减速器(没什么令人兴奋的,但就在这里)

const initialState = {
    people: []
};

export default function(state=initialState, action) {
    if (action.type === ActionTypes.ADD_USER) {
        let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
        return {people: newPeople};
    }
    return state;
};

如果您需要查看我的路由器是如何使用 redux 配置的

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

var Route = (
  <Provider store={store}>
    <Router history={createBrowserHistory()}>
      {Routes}
    </Router>
  </Provider>
);

更新

看起来如果我在连接中省略我自己的调度(目前在上面我正在显示 fetchUsers),我将获得免费调度(只是不确定这是否是带有异步操作的设置通常的工作方式) .人们是混合搭配还是全有或全无?

[mapDispatchToProps]

您通常可以根据自己的喜好进行混搭。

可以传递dispatch作为道具,如果这是你想要的:

export default connect(mapStateToProps, (dispatch) => ({
    ...bindActionCreators({fetchUsers}, dispatch), dispatch
}))(Users);

我不确定 fetchUsers 是如何使用的(作为异步函数?),但您通常会使用 bindActionCreators 之类的东西来 自动绑定 dispatch 然后你就不用担心直接在连接的组件中使用 dispatch

使用 dispatch 目录将 dumb、无状态组件与 redux 结合起来。这会降低它的便携性。

虽然您可以将 dispatch 作为 dispatchToProps 的一部分向下传递,但我建议您避免直接从您的组件中访问 storedispatch。在 connect 的第二个参数 dispatchToProps

中传递一个绑定动作创建者似乎会更好地为您服务

查看我在此处发布的示例 ,了解如何通过这种方式传递 "already bound action creator",您的组件不需要直接了解或依赖 store/dispatch。

抱歉长话短说。我会更新更多信息。

默认情况下 mapDispatchToProps 就是 dispatch => ({ dispatch })
因此,如果您不指定 connect() 的第二个参数,您将在组件中将 dispatch 作为 prop 注入。

如果您将自定义函数传递给 mapDispatchToProps,您可以对该函数执行任何操作。
几个例子:

// inject onClick
function mapDispatchToProps(dispatch) {
  return {
    onClick: () => dispatch(increment())
  };
}

// inject onClick *and* dispatch
function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(increment())
  };
}

为了节省您的输入时间,Redux 提供了 bindActionCreators() 让您可以将其转换为:

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

进入这个:

import { bindActionCreators } from 'redux';

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

当道具名称与动作创建者名称匹配时甚至更短:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

如果您愿意,您绝对可以手动添加 dispatch

// injects increment, decrement, and dispatch itself
function mapDispatchToProps(dispatch) {
  return {
    ...bindActionCreators({ increment, decrement }), // es7 spread syntax
    dispatch
  };
}

没有关于您是否应该这样做的官方建议。 connect() 通常用作支持 Redux 的组件和不支持 Redux 的组件之间的边界。这就是为什么我们通常觉得注入 both 绑定动作创建者和 dispatch 没有意义。但如果你觉得你需要这样做,请随意。

最后,您现在使用的模式是一个比调用 bindActionCreators 更短的快捷方式。当您所做的只是 return bindActionCreators 时,您可以省略调用,而不是这样做:

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

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

可以这样写

export default connect(
  mapStateToProps,
  { increment, decrement } // injects increment and decrement
)(App);

但是,每当您想要更自定义的东西时,例如也传递 dispatch,您将不得不放弃这种漂亮的简短语法。