【问题标题】:Redux: using different reducers for a componentRedux:对一个组件使用不同的 reducer
【发布时间】:2018-01-23 17:16:33
【问题描述】:

我有一个组件 UsersList,我想用两个不同的 reducer 重用它 - 一个用于列出普通用户 (state.users.x),另一个用于列出管理员 (state.adminusers.x)。两种情况下的显示是一样的,只是状态在不同的地方,应用的api动作也不同(不同的endpoint有不同的业务规则)。

如何编写我的组件以便它可以使用任一减速器?

【问题讨论】:

  • Reducer 本身是状态容器,不负责 API 调用。如果你想访问不同的reducer,你可以在mapStateToProps订阅它们。但要调用不同的 API 端点,您需要访问不同的操作并在 componentDidMount 中有条件语句来调用它们。

标签: reactjs redux code-reuse


【解决方案1】:
  1. 照常编写 UsersList 组件,但不要将其连接到 redux。

例如:

import React, { Component } from 'react';
import { Table } from 'react-bootstrap';
import UserInviteRow from 'jsx/components/Lib/Users/UserInviteRow';

export class UsersList extends Component {

    render() {
        const { inviteUserToOrg } = this.props;

        return (
            <Table bordered hover>
                <thead>
                    <tr>
                        <th className="width-200">First Name</th>
                        <th className="width-250">Last Name</th>
                        <th>Email</th>
                        <th className="width-150">Last Login</th>
                        <th className="width-100">&nbsp;</th>
                    </tr>
                </thead>
                <tbody>
                    <UserInviteRow invitefxn={ inviteUserToOrg }/>
                    { this.renderRows() }
                </tbody>
            </Table>
        );
    }

    renderRows() {
        const { usersList } = this.props;
        if( ! usersList.length ) {
            return (
                <tr>
                    <td colSpan="5">
                        <em>No users exist for this non-profit</em>
                    </td>
                </tr>
            );
        }

        return usersList.map( (user) => {
            return (
                <tr key={user.key}>
                    <td>{user.firstName}</td>
                    <td>{user.lastName}</td>
                    <td>{user.correspondenceEmailAddress}</td>
                    <td>{ (user.lastSeen) ? formatTime(user.lastSeen) : '' }</td>
                    <td className="text-center">
                        { this.renderRemoveButton( user ) }
                    </td>
                </tr>
            );
        });
    }

    renderRemoveButton(user) {
        const { currentUser } = this.props;
        if( currentUser.key === user.key ) {
            // users cannot remove themselves
            return null;
        }

        return (
            <a className="text-danger" onClick={ () => { this.removeUser(user) } }>
                <em className="fa fa-times" />
            </a>
        );
    }

    removeUser( user ) {
        this.props.removeUserFromOrg(user.key);
    }
}

export default UsersList;
  1. 确保您的两个 reducer 都实现了您使用的操作函数,在本例中为 inviteUserToOrg 和 removeUserFromOrg。

  2. 创建连接到每个 reducer 的新容器组件

例如:

import { connect } from 'react-redux';
import { 
    inviteUserToOrg, 
    removeUserFromOrg 
} as actions from 'jsx/redux/modules/nonadminUsers'; 
import UsersList from 'jsx/components/Lib/Users/UsersList';

var NonadminUserList = connect(
  state => {
    return {
      usersList: state.users.usersList,
    };
  },
  actions
)(UsersList);

export default NonadminUserList;

和

import { connect } from 'react-redux';
import { 
    inviteUserToOrg, 
    removeUserFromOrg 
} as actions from 'jsx/redux/modules/adminUsers';
import UsersList from 'jsx/components/Lib/Users/UsersList';

var AdminUserList = connect(
    state => {
        return {
            usersList: state.adminusers.usersList,
        };
    },
    actions
)(UsersList);

export default AdminUserList;

现在对您的表示组件 UsersList 的更改将影响两个容器组件,并且每个容器组件都可以引用它自己的 reducer 状态和操作。

【讨论】:

  • 附带说明一下,在使用 redux 花费了更多时间之后,我得出的结论是,虽然这在技术上有效,但它是一个非常丑陋的修复;而且,作为一般规则,这些问题可以通过更喜欢将数据作为道具传递给组件并仅连接最高级别的视图组件来避免。
猜你喜欢
  • 2016-06-30
  • 1970-01-01
  • 2017-05-11
  • 2018-02-15
  • 2017-10-02
  • 1970-01-01
  • 2016-06-05
  • 2016-06-21
  • 2017-02-23
相关资源
最近更新 更多