Как правильно взаимодействовать между компонентами в реакции?Почему бы не использовать ссылки везде? - PullRequest
2 голосов
/ 28 сентября 2019

Я знаю, что этот вопрос задают много раз, но пока я не смог найти разумный ответ.

Если я хочу создать приложение, которое состоит из двух компонентов: кнопок и таймера, отображающеговремя.При нажатии кнопки таймер запускается / останавливается / сбрасывается.Для меня, как новичка в React, очевидный способ сделать это - создать методы start () pause () reset () внутри таймера, а затем нажать кнопку, чтобы вызвать эту функцию (используя ссылки).

Но, согласно React doc и всем учебным пособиям, этого следует избегать.Должно быть так, что методы start () pause () reset () хранятся в самом верхнем компоненте (родительском компоненте «button» и «timer»), и оттуда они должны управлять таймером.

Ночто в случае, если я хочу иметь 10 разных таймеров (один и тот же компонент разного дизайна)?Разве не было бы СУХОЙ кодировкой иметь методы запуска, паузы, сброса, определенные внутри таймера, чтобы верхний компонент не имел 30 методов?

Это гипотетический пример, пожалуйста, не давайте мне обходных путейЯ хотел бы понять причину наличия ВСЕЙ логики в верхнем компоненте, что делает дочерние компоненты не подлежащими повторному использованию в качестве автономного.

Ответы [ 2 ]

1 голос
/ 29 сентября 2019

Что ж, с моей точки зрения, вам не нужно иметь методы таймера в каком-либо верхнем компоненте, таймер должен знать только, что нажата кнопка, и в этом случае вы передаете событие click для таймера через реквизиты, то есть для предположения, что таймери кнопка оказываются внутри той же функции.Это означает, что никаких ссылок тоже нет.Когда компонент таймера получит новый реквизит, он будет отрендерен.

То же самое будет работать для нескольких таймеров внутри компонента таймеров.

1 голос
/ 28 сентября 2019

Учитывая ваш пример, цель перемещения реализации «вверх» по слоям заключается в том, чтобы иметь возможность использовать один и тот же компонент таймера в разных частях вашего приложения, где, возможно, start () должен вести себя по-разному каждый раз.Сам компонент не мог бы знать, что должно делать каждое конкретное «стартовое» событие, так как компонент не должен знать, как оно использовалось в любое время.

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

Это на самом деле обеспечивает СУХОЙ, так как вам нужен 1 таймер (логика запуска, пауза, остановка, «таймер достиг» может быть и т. д.), а затем каждыйвызывающий абонент подключается к тому, что он хочет делать, когда происходят эти события.

Если вы думаете о структуре самого React и его события жизненного цикла, это одно и то же.«ComponentDidMount» ничем не отличается от «запуска» вашего таймера, например, просто другой контекст.Концептуальная мысль та же

РЕДАКТИРОВАТЬ: Важно подумать о том, что остается фиксированным в вашем компоненте для всех и что должно быть настраиваемым.Например, ваш таймер всегда будет срабатывать один раз в секунду, верно?Поэтому часть отслеживания времени всегда будет постоянной для вашего приложения, она должна находиться внутри компонента.Компонент должен иметь набор методов Start, Pause, Stop, определенных в нем, так как stop всегда просто останавливает счет, start всегда возобновляет его.Но вам нужно будет выставить OnStart, OnStop, OnPause, чтобы вызывающие абоненты могли подключить логику, необходимую им, используя ваш таймер.Я не знаю, смогу ли я объяснить это достаточно хорошо ...

РЕДАКТИРОВАТЬ 2: Например, проверьте ниже метод запуска таймера ниже:

 function Start(){
    // set the interval here or wtver way you will have to measure ticks
// ...
// ...
    if(this.props.OnStart)
     this.props.OnStart();
    }

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

РЕДАКТИРОВАТЬ 3: Хорошо, так что ..если кнопка нажата, мы запустим таймер и затем вызовем любые хуки, заданные реквизитом

 function OnEveryClick(){
    // here you will write anything you want your component to do every time the button is clicked, regardless of who is the caller, like our previous Start method
this.Start();
    }

function ButtonClicked(){
// first you call your method every time
 this.OnEveryClick();
// then if the caller also wants to do some stuff, you evaluate their function aswell
  if(this.props.OnSubmit)
    this.props.OnSubmit();
}

Затем на рендере вы сделаете что-то вроде этого

<button onClick={this.ButtonClicked.bind(this)}>
...