如何使用带 Redux 的连接从 this.props 获得简单的调度?

Posted

技术标签:

【中文标题】如何使用带 Redux 的连接从 this.props 获得简单的调度?【英文标题】:How to get simple dispatch from this.props using connect w/ Redux? 【发布时间】:2016-03-31 05:18:59 【问题描述】:

我有一个简单的 React 组件,我连接起来(映射一个简单的数组/状态)。为了避免引用 store 的上下文,我想要一种直接从 props 获取“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]

【问题讨论】:

【参考方案1】:

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

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

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

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

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

【讨论】:

你的建议行不通。你会得到一个未绑定的fetchUsers 作为道具注入。快捷表示法仅在您将对象作为第二个参数传递时才有效。当你传递一个函数时,你必须自己调用bindActionCreatorsdispatch =&gt; ( ...bindActionCreators( fetchUsers , dispatch), dispatch ) 为什么直接在bindActionCreators中传播和传入dispatch? dispatch =&gt; ( bindActionCreators( dispatch, fetchUsers , dispatch))【参考方案2】:

虽然您可以将dispatch 作为dispatchToProps 的一部分向下传递,但我建议避免直接从您的组件中访问storedispatch。似乎通过在连接的第二个参数dispatchToProps 中传递绑定动作创建者@

会更好地为您服务

请参阅我在https://***.com/a/34455431/2644281 此处发布的示例,说明如何以这种方式传递“已绑定的动作创建者”,您的组件无需直接了解或依赖于 store/dispatch。

对不起,简短。我会更新更多信息。

【讨论】:

【参考方案3】:

默认情况下mapDispatchToProps 只是dispatch =&gt; ( dispatch )。 因此,如果您不指定 connect() 的第二个参数,您将在组件中注入 dispatch 作为道具。

如果您将自定义函数传递给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-aware 和 Redux-unaware 组件之间的边界。这就是为什么我们通常觉得注入 绑定动作创建者和dispatch 是没有意义的。但是,如果您觉得需要这样做,请随意。

最后,您现在使用的模式是一个比调用bindActionCreators 更短的快捷方式。当您所做的只是返回 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

【讨论】:

@DanAbramov btw 是bindActionCreators(actionCreators, dispatch) 中的第二个参数可选吗?我在// es7 spread syntax 行的代码中注意到,dispatch 没有传递给bindActionCreators 增量法里面是什么? es7 传播语法应该是function mapDispatchToProps(dispatch) return ...bindActionCreators( increment, decrement ), dispatch ;

以上是关于如何使用带 Redux 的连接从 this.props 获得简单的调度?的主要内容,如果未能解决你的问题,请参考以下文章

Jest/Enzyme 单元测试:如何将存储传递给使用 redux 4 和 react-redux 6 连接功能的浅层组件

当输入字段已经使用 useState() 映射时,如何使用 useSelector() 连接 redux 存储

如何对 React-Redux 连接组件进行单元测试?

react和redux怎么连接?

从 redux、aggrid 和 react 钩子重新选择/连接的组合

无法在 react native 中使用 redux 连接多个组件