Есть ли способ обновить функцию в списке событий в функциональном компоненте React?

#javascript #reactjs

Вопрос:

Мне нужно найти способ использовать как переменную, объявленную внутри функционального компонента, так и часть реквизитов функционального компонента внутри функции обратного вызова в списке событий mousemove.

До сих пор у меня есть приведенный ниже код, но, похоже, реквизиты не обновляются в функции onHover.

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

Есть ли способ убедиться, что функция onHover ссылается на самую последнюю версию реквизита?

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

 function FunctionalComp(props){

    let variableNeededInOnHover = null;

    useEffect(()=>{
        window.addEventListener("mousemove", onHover, true)
        return () => {
            window.removeEventListener("mousemove", onHover, true)
        }
    }, [])

    function onHover(event) { 
        console.log(props.value)    // stays 1
        console.log(variableNeededInOnHover)
    }
    
    return ( <div>{props.value}</div> ) // Updates to show a value of 2
}
 

Есть ли способ решить эту проблему?

Редактировать:

Я попробовал предлагаемое решение Taxel, и, похоже, variableNeededInOnHover оно сохраняет нулевое значение, даже если я установил его значение в useEffect крючке, имитируя метод жизненного цикла componentDidMount ().

 function FunctionalComp(props){

    let variableNeededInOnHover = null;

    useEffect(()=>{
        variableNeededInOnHover = "Non Null Value";
    }, [])

    useEffect(()=>{
        window.addEventListener("mousemove", onHover, true)
        return () => {
            window.removeEventListener("mousemove", onHover, true)
        }
    }, [props.value])

    function onHover(event) { 
        console.log(props.value)    // stays 1
        console.log(variableNeededInOnHover)
    }
    
    return ( <div>{props.value}</div> ) // Updates to show a value of 2
}
 

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

1. добавление props.value в текущий пустой массив зависимостей useEffect должно помочь.

2. @Taxel Я попытался добавить props.value его в зависимость, и props.value он действительно обновляется, но каким-то образом variableNeededInOnHover сохраняет исходное null значение…

3. variableNeededInOnHover необходимо объявить с помощью функции useState. В противном случае он сбрасывается до нуля при каждом рендеринге.

4. «но каким — то образом variableNeededInOnHover сохраняет исходное нулевое значение…» Любое «внешнее» значение должно быть объявлено как зависимость от useEffect , чтобы обработчики событий воссоздавались всякий раз, когда меняется одно из этих значений. Т. е. вам нужно [props.value, variableNeededInOnHover] . reactjs.org/docs/hooks-effect.html

Ответ №1:

Я не уверен на 100%, что это решит вашу проблему, так как у вас нет возможности обновить props.value в примере. Как правило, вам нужно использовать состояние реакции для любых значений, которые будут изменены, и вы хотите вызвать повторную отправку. Реакция не будет знать о let том, что где-то обновляется.

Я добавил пример ниже, который показывает обновляемое значение.

 function FunctionalComp(props){

    const [value, setValue] = React.useState(props.value);

    React.useEffect(()=>{
        setValue(oldValue => oldValue   1);
    }, [])

    React.useEffect(()=>{
        window.addEventListener("mousemove", onHover, true)
        return () => {
            window.removeEventListener("mousemove", onHover, true)
        }
    }, [value])

    function onHover(event) { 
        console.log(value)    // stays 1
    }
    
    return ( <div>{value}</div> ) // Updates to show a value of 2
}

ReactDOM.render(
  <FunctionalComp value={1} />,
  document.getElementById("react")
); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>