将类组件(具有本地状态)转换为无状态功能组件&容器

时间:2017-02-10 19:18:45

标签: reactjs redux

我是react-redux的新手,目前正在开展一个项目,我们的软件架构团队要求我们将所有组件编写为无状态功能组件(在React 0.14中引入)以及每当我们需要通过时他们是redux状态的一部分我们应该使用容器。

我的问题是: 这种模式适用于每个组件吗?即使对于具有自己的“状态”(不是还原状态)的基于类的组件?是否可以将所有类组件重写为无状态功能组件和容器?

我问的原因实际上更具体: 团队决定使用reactstrap-tabs在我们的组件中实现选项卡功能。选项卡将位于父组件内,每个选项卡内将显示不同的子组件。从文档中可以看出,父选项卡组件应该实现为基于类的组件(处理this.state)。是否可以将其重写为无状态功能组件和容器?

任何帮助都会非常感激,因为我被困在这上面了。以下是示例代码......

import React from 'react';
import { TabContent, TabPane, Nav, NavItem, NavLink, Card, Button, CardTitle, CardText, Row, Col } from 'reactstrap';
import classnames from 'classnames';
import MyFirstChildComponent from '/components/MyFirstChildComponent';
import MySecondChildContainer from '/containers/MySecondChildContainer';


export default class TabbedParent extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.state = {
      activeTab: '1'
    };
  }

  toggle(tab) {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }
  }

  render() {
    return (
      <div>
        <Nav tabs>
          <NavItem>
            <NavLink
              className={classnames({ active: this.state.activeTab === '1' })}
              onClick={() => { this.toggle('1'); }}
            >
              MyFirstTab
            </NavLink>
          </NavItem>
          <NavItem>
            <NavLink
              className={classnames({ active: this.state.activeTab === '2' })}
              onClick={() => { this.toggle('2'); }}
            >
              MySecondTab
            </NavLink>
          </NavItem>
        </Nav>
        <TabContent activeTab={this.state.activeTab}>
          <TabPane tabId="1">
            <Row>
              <Col sm="12">
                <MyFirstChildComponent />
              </Col>
            </Row>
          </TabPane>
          <TabPane tabId="2">
            <Row>
              <Col sm="6">
                <MySecondChildContainer />
              </Col>
            </Row>
          </TabPane>
        </TabContent>
      </div>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

听起来您的架构团队希望您将状态集中在Redux存储中,并询问您是否可以使用维护其自身状态的组件。那里显然存在冲突,但是您可以通过将选项卡状态保留在商店中,使用容器在切换时更新选项卡以及调度操作然后选择选项卡来实现选项卡的所需。

如果您无法更改UI的商店结构,那么我认为您只能进行设计和组件选择,以便与商店中可用的数据一起使用。我不确定你的架构团队是多么不灵活。

您的示例的简单实现可能如下所示:

import MySecondChildContainer from '/containers/MySecondChildContainer';

const TabbedParent = ({activeTab, clickHandler}) =>
      <div>
        <Nav tabs>
          <NavItem>
            <NavLink
              className={classnames({ active: activeTab === '1' })}
              onClick={() => clickHandler('1')}
            >
              MyFirstTab
            </NavLink>
          </NavItem>
          <NavItem>
            <NavLink
              className={classnames({ active: activeTab === '2' })}
              onClick={() => clickHandler('2')}
            >
              MySecondTab
            </NavLink>
          </NavItem>
        </Nav>
        <TabContent activeTab={activeTab}>
          <TabPane tabId="1">
            <Row>
              <Col sm="12">
                <MyFirstChildComponent />
              </Col>
            </Row>
          </TabPane>
          <TabPane tabId="2">
            <Row>
              <Col sm="6">
                <MySecondChildContainer />
              </Col>
            </Row>
          </TabPane>
        </TabContent>
      </div>

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

const mapDispatchToProps = dispatch => ({
    clickHandler(id) { dispatch(TabClicked(id)) },
});

export connect(mapStateToProps, mapDispatchToProps)(TabbedParent);