#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. Да, мне потребовалось некоторое время, чтобы понять, что значения в эффектах / обратных вызовах могут быть устаревшими, несмотря на то, что они, похоже, напрямую ссылаются на состояние. Я нашел этот блог, на который я ссылался, действительно полезным для расширения моего понимания того, почему все работает не так, как я ожидал.