我应该使用React State进行用户交互(切换可见性类)吗?

问题描述 投票:2回答:1

我正在开发一个UI库,我的一些组件根据用户的一些交互来改变他们的“状态”。

例如,用户点击手风琴面板的标题会导致手风琴面板打开并变为可见。通过将visible修饰符添加到手风琴面板来实现此状态,如下所示:

<div class="accordion">
    <div class="accordion_panel-visible">
        <div class="accordion_title">foo</div>
        <div class="accordion_content">bar</div>
    </div>
    <div class="accordion_panel">
        <div class="accordion_title">fizz</div>
        <div class="accordion_content">buzz</div>
    </div>
</div>

我之前的假设是React State应该用于根据一些后端数据重新渲染组件。但是,基于查看来自其他UI库等的源代码,它们似乎也在处理具有React State的UI状态。

所以使用React,我可以通过使用原始DOM API实现我想要的东西(如这里的例子所示 - https://reactjs.org/docs/refs-and-the-dom.html):

Accordion.defaultProps = {
    name: 'accordion'
};

class Accordion extends React.Component {
    toggle(event) {
        const panel = event.target.closest('[data-component="panel"]');
        const operator = panel.modifier('active') ? 'unset' : 'set';

        panel.modifier('active', operator); 
    }

    render() {
        return (
            <Module {...this.props}>
                {this.props.panels.map(({ title, content }, index) => (
                    <Component name='panel' key={index}>
                        <Component name='title' onClick={this.toggle}>{title}</Component>
                        <Component name='content'>{content}</Component>
                    </Component>
                ))}
            </Module>
        )
    }
}

这一切都很好 - 但我实际上是在一个React组件中进行DOM操作,我应该避免使用它。在这种情况下,我应该使用React State和Refs(而不是直接的DOM操作)。为了实现上述相同的目的,我相信我能做到:

Accordion.defaultProps = {
    name: 'accordion'
};

class Accordion extends React.Component {
    constructor(props) {
        super(props);

        this.panels = [];
        this.state = { activePanel: null };
    }

    toggle(index) {
        this.setState({ 
            activePanel: (this.panels[index] === this.state.activePanel) ? null : this.panels[index]
        });
    }

    isActive(index) {
        return (this.panels[index] === this.state.activePanel) ? true : false;
    }

    render() {
        return (
            <Module {...this.props}>
                {this.props.panels.map(({ title, content }, index) => (
                    <Component name='panel' 
                        key={index} 
                        ref={ref => this.panels[index] = ref}
                        modifiers={this.isActive(index) ? 'active' : false}
                    >
                        <Component name='title' onClick={this.toggle.bind(this, index)}>
                            {title}
                        </Component>
                        <Component name='content'>{content}</Component>
                    </Component>
                ))}
            </Module>
        )
    }
}

(我知道上面代码片段的行为会关闭兄弟面板,而第一个片段不是这种情况,但这是微不足道的,可以忽略)。

所以我的问题是,我是否应该利用React State(即后一个例子)?

感觉就好像我的应用程序基于用户交互显示/隐藏/打开/关闭UI元素,这些用户交互不需要/修改/发布/更新/获取/接收数据,然后React实际上不应该关心它们。

但最重要的是 - 这取决于偏好吗?我应该决定React是否应该关心这个问题吗?在一天结束时,react是一个工具,我目前用于在后端自由环境中创建和呈现UI组件的工具。我现在真的很困惑,并且不确定我是否能真正看到在这种情况下使用state的好处。

谢谢!

reactjs user-interface ref react-state-management
1个回答
1
投票

正如我理解您的担忧,您只想将后端/通信和业务逻辑放入“React状态”。但正如你自己指出的那样,还有与UI元素相关的状态。手风琴被关闭/打开等。

可以将其分为两类:

   - UI State (only for representation purposes)
   - Business Logic state

您可以将React的组件状态用于两者。

在构建或使用UI组件库时,为了进行封装,通常会在这些库中保留/管理状态。对于复杂的应用程序,我建议使用一些更强大的状态管理,如react-redux。但也存在人们使用react-redux进行UI和业务逻辑状态的情况。

从可重用性的角度来看,我建议让UI组件不知道实际的应用程序用例(如Accordion,FancyButton,Snackbar等)。另一个组件集合,包括整个页面或其中的一部分(页眉,页脚,导航,MainView等)。

然后 - 当使用redux时 - 你可以拥有所谓的容器,它将组件与redux的存储/状态管理连接起来。

在任何情况下,都应该避免使用refs进行“简单”状态修改。通常这只是必需的,如果你包括第三方库(jQuery之类)或WebComponents/Custom Elements,因为它们可能不能很好地与React道具等开箱即用。

关于评论中的问题:具有呈现FrequentlyAskedQuestions(FAQ)的任务,组件可能如下所示:

应用程序相关的UI组件(“愚蠢”),. / component /FAQ.js:

const FAQ = ({faqs}) => (
  <Accordion>
    {faqs.map(faq => (
      <AccordionPane title={faq.title} content={faq.text} />
    ))}
  </Accordion>
)

并且 - 使用redux - 相应的Container,./ container /FAQ.js:

import {connect} from 'react-redux'
import FAQ from './FAQ'

const mapStateToProps = state => state.faqs

export default connect(mapStateToProps)(FAQ)
© www.soinside.com 2019 - 2024. All rights reserved.