Как использовать переменную состояния (useState) в EventHandler - PullRequest
1 голос
/ 09 июля 2019

У меня есть React Functional Component, который получает реквизит с переменной из useState ().Это работает нормально, но если я использую его в EventListener, он не обновляется.Я попробовал следующее, но все равно это не работает.

Может быть, кто-то может объяснить, почему.

Спасибо

Я ожидал бы, что x будет обновленным числом, но оно всегда имеетзначение начальной настройки EventHandler.

import React, { useState, useEffect } from "react";
import ReactDom from "react-dom";

const App = () => {
   const [num, setNum] = useState(50);

  return (
    <div>
       <button onClick={() => setNum(prev => prev + 1)}>Test</button>
       <div>{num}</div>
       <Child num={num} />
    </div>
  );
};

const Child = ({ num }) => {
  let x = 0;
  const md = () => {
  console.log(num, x);
};

useEffect(() => {
x = num;
  }, [num]);

useEffect(() => {
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, []);

  return <div id="box">click {num}</div>; 
};

ReactDom.render(<App />, document.getElementById("app"));

1 Ответ

1 голос
/ 09 июля 2019

Каждый рендер вашего Child получит новый x, новый props объект и т. Д. Однако вы привязываете прослушиватель событий только один раз и захватывает только начальное значение props.num.

Два способа исправить:

Перепривязать прослушиватель событий при изменении num, передав num как зависимость от вашего эффекта для привязки прослушивателя событий:

const Child = ({ num }) => {

  useEffect(() => {
    // no need to define this in main function since it is only
    // used inside this effect
    const md = () => { console.log(num); };
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, [num]);

  return <div id="box">click {num}</div>; 
};

Или используйте ref для хранения значения num и привязки слушателя событий к ref. Это дает вам уровень косвенности для обработки изменений:

const Child = ({ num }) => {
  const numRef = useRef();  // will be same object each render
  numRef.current = num; // assign new num value each render

  useEffect(() => {
    // no need to define this in main function since it is only
    // used inside this effect
    // binds to same ref object, and reaches in to get current num value
    const md = () => { console.log(numRef.current); };
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, []);

  return <div id="box">click {num}</div>; 
};
...