Реагировать на обработчик события ловушки useState, используя начальное состояние - PullRequest
2 голосов
/ 20 марта 2019

Я все еще ловлю голову на крюках реакции, но изо всех сил пытаюсь понять, что я здесь делаю не так.У меня есть компонент для изменения размеров панелей, при новом изменении края я обновляю значение в состоянии, затем у меня есть обработчик событий для mousemove, который использует это значение, однако он не обновляется после изменения значения.

Вот мой код:

export default memo(() => {
  const [activePoint, setActivePoint] = useState(null); // initial is null

  const handleResize = () => {
    console.log(activePoint); // is null but should be 'top|bottom|left|right'
  };

  const resizerMouseDown = (e, point) => {
    setActivePoint(point); // setting state as 'top|bottom|left|right'
    window.addEventListener('mousemove', handleResize);
    window.addEventListener('mouseup', cleanup); // removed for clarity
  };

  return (
    <div className="interfaceResizeHandler">
      {resizePoints.map(point => (
        <div
          key={ point }
          className={ `interfaceResizeHandler__resizer interfaceResizeHandler__resizer--${ point }` }
          onMouseDown={ e => resizerMouseDown(e, point) }
        />
      ))}
    </div>
  );
});

Проблема в функции handleResize, в которой должна использоваться последняя версия activePoint, которая будет представлять собой строку top|left|bottom|right, но вместо этого будет null.

1 Ответ

4 голосов
/ 20 марта 2019

useRef для чтения будущей стоимости

В настоящее время ваша проблема в том, что вы читаете значение из прошлого. Когда вы определяете handleResize, он относится к этому рендеру, поэтому при повторном рендеринге ничего не происходит со слушателем событий, поэтому он все равно считывает старое значение из своего рендера.

Чтобы исправить это, вы должны использовать ссылку через useRef, которую вы постоянно обновляете, чтобы вы могли прочитать текущее значение.

Пример (ссылка на jsfiddle):

  const [activePoint, _setActivePoint] = React.useState(null);

  // define a ref
  const activePointRef = React.useRef(activePoint);

  // in place of original `setActivePoint`
  const setActivePoint = x => {
    activePointRef.current = x; // keep updated
    _setActivePoint(x);
  };

  const handleResize = () => {
    // now when reading `activePointRef.current` you'll
    // have access to the current state
    console.log(activePointRef.current);
  };

  const resizerMouseDown = /* still the same */;

  return /* return is still the same */
...