Должен ли я использовать React State для взаимодействия с пользователем (для переключения классов видимости)? - PullRequest
0 голосов
/ 04 июня 2018

Я занимаюсь разработкой библиотеки пользовательского интерфейса, и некоторые из моих компонентов меняют свое «состояние» на основе некоторого взаимодействия с пользователем.

Например, пользователь нажимает на заголовок аккордеонной панели, что приводит к тому, что аккордеонная панельоткрыть и стать видимым.Это состояние достигается добавлением модификатора visible на панель аккордеона, например, так ::1004*

<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 следует использовать для повторного рендеринга компонента, основанного на некотором обратномконечные данные.Однако, основываясь на взгляде на исходный код из других библиотек пользовательского интерфейса и т. Д., Кажется, что они также обрабатывают состояния пользовательского интерфейса с помощью React State.

Таким образом, используя 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>
        )
    }
}

, который прекрасно работает, но япо сути, следует избегать манипуляций с DOM из компонента React, который я постоянно читаю. В этом случае я должен использовать React State и Refs (вместо прямых манипуляций с DOM). Для достижения того же, что и выше, я считаю, что мог быdo:

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 для этого (т.е. последний пример)?

Такое ощущение, что мое приложение отображает / скрывает / открывает / закрывает элементы пользовательского интерфейса на основе пользовательские взаимодействия , которые не требуют / изменяют / публикуют / обновляют / получают / получают данные каким-либо образом, тогда React не должен заботиться о них.

Но самое главное - - этоэтот до предпочтения ?Должно ли это быть me , кто решает, должен ли React заботиться об этом?В конце концов, реакция - это инструмент, инструмент, который я сейчас использую для создания и рендеринга компонентов пользовательского интерфейса в серверной среде.Я просто очень запутался прямо сейчас, и не уверен, что могу увидеть преимущества использования state в этом контексте.

Спасибо!

1 Ответ

0 голосов
/ 04 июня 2018

Насколько я понимаю, вы хотели бы перевести в бэкэнд / коммуникацию и бизнес-логику "состояние реакции".Но, как вы сами указали, существует также состояние, связанное с элементами пользовательского интерфейса.Аккордеон закрыт / открыт и т. Д.

Можно разделить это на две категории:

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

Вы можете использовать состояние компонента React для обоих.

При создании или использовании библиотек компонентов пользовательского интерфейса в них часто сохраняется / управляется состояние для инкапсуляции.Для сложных приложений я бы рекомендовал использовать более мощные средства управления состоянием, такие как response-redux .Но есть также случаи, когда люди используют реактив-редукс для пользовательского интерфейса и Состояние бизнес-логики.

С точки зрения возможности повторного использования я бы рекомендовал иметь компоненты пользовательского интерфейса, которые не знают о реальном приложениисценарий использования (например, Аккордеон, FancyButton, Snackbar и т. д.).И еще одна коллекция Компонентов, которые составляют целую страницу или ее части (Верхний колонтитул, Нижний колонтитул, Навигация, MainView и т. Д.).

Затем - при переходе с избыточным кодом - вы можете иметь так называемые Контейнеры, которые соединяютКомпоненты с управлением хранением / состоянием избыточности.

В любом случае следует избегать использования ссылок для «простых» модификаций состояния.Обычно это требуется только в том случае, если вы включаете сторонние библиотеки (например, jQuery) или WebComponents / Custom Elements , поскольку они могут не очень хорошо работать с React-подпрограммами и т. Д. Из коробки.

Относительновопрос из комментариев: имея задачу рендеринга FrequentlyAskedQuestions (FAQs), компонент может выглядеть так:

Компонент UI, связанный с приложением («тупой»), ./components/FAQ.js:

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

И - используя приставку - соответствующий контейнер, ./containers/FAQ.js:

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

const mapStateToProps = state => state.faqs

export default connect(mapStateToProps)(FAQ)
...