Оба обработчика onClick
в родительском компоненте воссоздаются при каждом рендеринге, так как они имеют замыкание в поле состояния number
.
Проблема в том, что свойство onClick
, отправленное дочернему компоненту, используется в обратном вызове ref
, который реагирует только во время первоначального рендеринга из-за пустого списка зависимостей.Поэтому onClick
prop, полученный Child в последующих рендерах, вообще не используется.
Попытка устранить эту ошибку, удалив параметр зависимости или отправив props.onClick, как в списке зависимостей, мы попадаем в проблему из-запредостережение, упомянутое в документации.https://reactjs.org/docs/refs-and-the-dom.html
Таким образом, вы добавляете нулевую обработку и видите, что ваш обновленный обратный вызов теперь вызывается, но ... все более ранние обратные вызовы также вызываются, поскольку мы не удалили эти прослушиватели событий.
const ref = useCallback((ref) => {
if(!ref) return;
ref.innerHTML = 'This Doesnt';
ref.addEventListener('click',() => {
props.onClick!('')
})
}, [props.onClick])
Я полагаю, что это всего лишь эксперимент, проводимый в рамках изучения хуков, в противном случае нет необходимости идти окольным путем, чтобы вызвать onClick
из обратного вызова ref.Просто передайте его как реквизит div
.
Редактировать:
Согласно вашему комментарию, поскольку это не просто эксперимент, а упрощение некоторых подлинных требований, где требуется обработчик кликовдля установки через addEventListener
, вот возможное решение:
const ref = useRef(null);
useEffect(() => {
if(!ref.current) return;
ref.current.innerHTML = 'This Doesnt';
const onClick = () => props.onClick!('');
ref.current.addEventListener('click',onClick)
// return the cleanup function to remove the click handler, which will be called before this effect is run next time.
return () => {ref.current.removeEventListener("click", onClick)}
}, [ref.current, props.onClick]);
В основном нам нужно использовать useEffect
, чтобы у нас была возможность удалить старого слушателя перед добавлением нового.
Надеюсь, это поможет.