React устанавливает перехват из вызова функции внешнего компонента

#javascript #reactjs #react-hooks

#javascript #reactjs #реагирующие перехваты

Вопрос:

Я тестирую новые перехваты React и столкнулся с поведением, которое не могу исправить (и не понимаю ни того, ни другого). В принципе, у меня есть мой функциональный компонент и внутри него функция, в которой я устанавливаю перехват. Эта функция передается отрисованному компоненту и вызывается из этого последнего отрисованного компонента с использованием реквизитов. Жаль, что перехваты родительского компонента не обновляются соответствующим образом!

Я знаю, это может показаться трудным для понимания, но я воспроизвел ошибку здесь https://codesandbox.io/s/vvwp33l7o5

Как вы можете видеть, в App компоненте у меня есть onResize функция, которая должна обновлять counter перехват. Эта функция передается ResizeObserverContainerHook компоненту, и из этого последнего вызывается при изменении размера ResizeObseverContainerHook div. Как вы можете видеть, width и height переменные в onResize функции верны, но counter перехват, похоже, не обновляется! Фактически, он остается равным 1 навсегда.

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

Есть идеи, как я могу сделать так, чтобы это setCounter работало примерно 12 из index.js ?

Ответ №1:

Другой ответ немного запутан — то, что вы делаете, прекрасно. Когда говорится, что не вызывать перехваты изнутри материала, это означает, что не вызывайте фактический API условно или из циклов, например, условно определяющий useEffect или useState .

Ваша проблема связана с пустым массивом, который вы передаете эффекту в Observer.js поскольку он пуст, эффект никогда не обновляется, поэтому замыкание устаревшее, так что при вызове onResize функции setState counter значением всегда будет начальное значение, равное нулю.

Вам нужно, чтобы это useEffect зависело от чего-то, чтобы при обновлении компонента он очищал предыдущий эффект и прикреплял свежую версию onResize функции к ResizeObserver.

Я немного покопался в вашей песочнице: https://codesandbox.io/s/x9z7k245lq?fontsize=14

Теперь он передает состояние счетчика компоненту Observer, и эффект будет запускаться при каждом изменении счетчика. Дело в том, что я также добавил некоторые ссылки в индекс для отслеживания высоты / ширины, чтобы состояние не всегда обновлялось, иначе оно будет бесконечно зацикливаться. Я думаю, вы можете думать об этом как shouldComponentUpdate .

Требуется некоторое время, чтобы правильно продумать перехваты. Если вы хотите прочитать хорошую статью о перехватах и избежать некоторых ошибок, связанных с пустым массивом и устаревшими замыканиями, ознакомьтесь с этим: https://overreacted.io/making-setinterval-declarative-with-react-hooks /

Комментарии:

1. Хм, теперь это имеет больше смысла! Но .. Можно ли было бы не передавать counter в Observer ? Observer должен быть более универсальным компонентом, он должен просто запускать функцию, когда ее div элемент был изменен. Затем, как правило, эта функция обновляет состояние компонента, который отображает Observer .

2. О да, я думаю, вы могли бы просто совершенно не передавать counter вниз, на самом деле это ничего не делает, поэтому вы могли бы просто не передавать второй аргумент в useEffect — я просто пытался избежать пустого [] . При использовании этой реализации следует учитывать, что в настоящее время она не выполняет бесконечный цикл, потому что в onResize функции проверяется ширина / высота.

3. Да, мне потребовалось некоторое время, чтобы понять, что значения в эффектах / обратных вызовах могут быть устаревшими, несмотря на то, что они, похоже, напрямую ссылаются на состояние. Я нашел этот блог, на который я ссылался, действительно полезным для расширения моего понимания того, почему все работает не так, как я ожидал.