如何使用 react-redux 将 ReactJS 组件正确连接到 Redux?

How to properly connect a ReactJS component to Redux using react-redux?

我正在尝试在 React 组件与 Redux 之间建立我的第一个连接,以从我的节点 API 收集数据。

目前这是一个简单的组件,但它会在未来增长并派生子组件,这些子组件将允许我构建一个完整的用户 CRUD 界面(列表、编辑、删除、查看等)。从这个意义上讲,我需要将动作函数连接到对象 this.props 以便它可以被子组件继承。

这是我的代码:

组件 UserGrid - 将加载用户信息的 table 数据网格

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

class UserGrid extends React.Component {
  componentWillMount() {
    this.props.fetchUsers();
  }

  render() {
    const mappedUsers = users.map(user => <li>{user.email}</li>);
    return (
            <div>
              <ul>{mappedUsers}</ul>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        users: state.users
    }
}

export default connect(
    mapStateToProps, 
    bindActionCreators(userActions, dispatch)
)(UserGrid);

My userAction,这将有效地从 AJAX 调用加载用户:

import axios from "axios";

export function fetchUsers() {
  return function(dispatch) {
    axios.get("/api/users")
      .then((response) => {
        dispatch({type: "FETCH_USERS_FULFILLED", payload: response.data});
      })
      .catch((err) => {
        dispatch({type: "FETCH_USERS_REJECTED", payload: err});
      })
  }
}

使用此代码我收到以下错误:

Uncaught ReferenceError: dispatch is not defined
    at Object.<anonymous> (bundle.js:37984)
    at __webpack_require__ (bundle.js:556)
    at fn (bundle.js:87)
    at Object.<anonymous> (bundle.js:37711)
    at __webpack_require__ (bundle.js:556)
    at fn (bundle.js:87)
    at Object.<anonymous> (bundle.js:8466)
    at __webpack_require__ (bundle.js:556)
    at fn (bundle.js:87)
    at Object.<anonymous> (bundle.js:588)
(anonymous) @ bundle.js:37984
__webpack_require__ @ bundle.js:556
fn @ bundle.js:87
(anonymous) @ bundle.js:37711
__webpack_require__ @ bundle.js:556
fn @ bundle.js:87
(anonymous) @ bundle.js:8466
__webpack_require__ @ bundle.js:556
fn @ bundle.js:87
(anonymous) @ bundle.js:588
__webpack_require__ @ bundle.js:556
(anonymous) @ bundle.js:579
(anonymous) @ bundle.js:582

将我的组件连接到创建的 Redux 服务的正确方法是什么?

我认为你不想在这里使用 bindActionCreators。这是 the docs 所说的(强调我的):

Normally you should just call dispatch directly on your Store instance. If you use Redux with React, react-redux will provide you with the dispatch function so you can call it directly, too.

The only use case for bindActionCreators is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it.

由于这不是您要执行的操作,因此您应该直接调用 dispatch。使用 react-redux,connect 会将其注入到您的道具中,因此您可以这样做:

componentWillMount() {
  this.props.dispatch(fetchUsers());
}

在您要连接的组件中,您需要定义函数 mapDispatchToProps。这个函数会把dispatch作为参数,connect调用函数的时候会收到这个参数。

这是从我最近的一个项目中提取的一些示例代码。

   function mapDispatchToProps(dispatch) {
        return {
            adminActions: bindActionCreators(adminOrdersActions, dispatch),
            schoolActions: bindActionCreators(schoolOrdersListActions, dispatch),
            userActions: bindActionCreators(userActions, dispatch)
        };
    }

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

现在定义了分派。

编辑:澄清一下,这样做现在可以让您使用以下语法访问您的操作。 this.props.actions.yourAction,或您在 mapDispatchToProps 中调用的任何操作。

这是我修改后的代码:

import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import * as userActions from '../../actions/userActions';

class UserGrid extends React.Component {

  componentWillMount() {
    console.log(JSON.stringify(this.props));

    //this.props.fetchUsers();
    this.props.actions.fetchUsers();
  }

  render() {

    const mappedUsers = users.map(user => <li>{user.email}</li>)

    return (
            <div>
            <ul>{mappedUsers}</ul>
            </div>
        )
    }
}

function mapStateToProps(state) {
    return {
        users: state.users
    }
}

function mapDispatchToProps(dispatch) {
    // this function will now give you access to all your useractions by simply calling this.props.actions.
    //if the key of this object would not be actions, but rather foobar, you will get your actions by 
    // calling this.props.foobar
    return {
        actions: bindActionCreators(userActions, dispatch)
    }
}

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

作为我不会使用bindActionCreators

您的组件应如下所示:

import React  from 'react';
import { connect } from 'react-redux';

import myAction from './my-action';

class MyComponent extends React.Component {

    componentDidMount() {
        this.props.myAction();
    }

    render() {
        return "Hi!"
    }

}

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

const mapDispatchToProps = (dispatch) => ({
    myAction: () => dispatch(myAction())
});

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