Что плохого в практике с refs в React?

Я учусь реагировать. Некоторые ребята из разных сайтов говорят всем, что использование refs-плохая практика (да, используя их вообще).

в чем дело? Это что-то плохое, что я прикреплю его, например, к дочернему компоненту (чтобы я мог получить доступ к внутреннему материалу)?

спасибо!

2 ответов


React требует от вас подумайте, как реагировать и refs - это своего рода бэкдор к DOM, который вам почти никогда не нужно использовать. Чтобы радикально упростить, способ мышления react заключается в том, что, как только состояние меняется, вы перерисовываете все компоненты пользовательского интерфейса, которые зависят от этого государства. React позаботится о том, чтобы обновлять только правильные биты DOM, что делает все это эффективным и скрывает DOM от вас (своего рода).

например, если в вашем компоненте размещен HTMLInputElement, в React вы подключите обработчик событий для отслеживания изменений входного элемента. Всякий раз, когда пользователь вводит символ, обработчик событий запускается, и в обработчике вы обновляете свое состояние новым значением элемента ввода. Изменение состояния инициирует повторную визуализацию компонента размещения, включая элемент ввода с новым значением.

вот что я имею в виду

import React from 'react';
import ReactDOM from 'react-dom';

class Example extends React.Component {

    state = {
      inputValue: ""
    }

    handleChange = (e) => {
      this.setState({
        inputValue: e.target.value
      })
    }

    render() {
        const { inputValue } = this.state
        return ( 
          <div>
            /**.. lots of awesome ui **/
            /** an input element **/
            <input value={inputValue} onChange={this.handleChange}} />
            /** ... some more awesome ui **/
          </div>
       )
  }
}


ReactDOM.render( <Example />, document.getElementById("app") );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


<div id="app">
</div>

обратите внимание, как каждый раз, когда изменяется входное значение, вызывается обработчик, вызывается setState и componet будет повторно отображать себя полностью.

его обычно плохая практика думать о refs, потому что у вас может возникнуть соблазн просто использовать refs и делать то, что говорит jQuery, что не является намерением архитектуры/мышления React.

лучший способ действительно понять это лучше, чтобы построить больше Реагировать приложения и компоненты.


Мда... Не уверен, что это квалифицируется как ответ, но он стал слишком длинным для комментария.

представьте, что у вас есть панель, которая содержит виджеты, показывающие различные состояния системы. Каждый виджет имеет свой собственный источник данных и свои собственные элементы управления. Возможно, время от времени они даже освежаются. Однако, когда пользователь хочет увидеть обновленный вид системы, на уровне панели мониторинга есть кнопка "Обновить". Реализация такой кнопки не является тривиальной.

Если вы находитесь в Приложение Redux - у вас будет выбор - "подделка" dispatch('refresh') для всех детей. Чтобы отделить его, каждый виджет при загрузке регистрирует действие, так что родитель просто проходит все действия и запускает их, когда важно обновить необходимо.

в системе Non Redux/Flux или в более сложных/динамических сценариях это может быть невозможно или может быть не так просто. Тогда может быть лучше, сложность мудрая, разоблачить refresh метод на всех виджетах, а затем открыть это от родителя (точнее, владельца):

class WidgetA extends React.Component {
    refresh() {
        console.log('WidgetA refreshed');
    }

    render() {
      return (
        <h3>WidgetA</h3>
      );
    }
}  

class WidgetB extends React.Component {
    refresh() {
        console.log('WidgetB refreshed');
    }

    render() {
      return (
        <h3>WidgetB</h3>
      );
    }
}  

class Dashboard extends React.Component {
    constructor() {
        super();

        this.onRefresh = this.handleRefresh.bind(this);
        this.onRegister = this.handleRegister.bind(this);
        this.widgets = [];
    }

    handleRegister(widget) {
        this.widgets.push(widget);
    }

    handleRefresh() {
        this.widgets.forEach((widget) => {
            widget.refresh();
        });
    }

    render() {
        return (
            <div>
                <button onClick={this.onRefresh}>Refresh</button>
                <hr />
                <WidgetA ref={this.onRegister} />
                <WidgetB ref={this.onRegister} />
            </div>
        );
    }
}

что-то вроде, что с меньшим количеством, конечно.

как примечание, Я upvoted @skav ответ и думаю, что эти сценарии следует избегать. Это исключение.

Пример CodePen