Значение ловушек React недоступно в функции прослушивателя событий - PullRequest
2 голосов
/ 24 марта 2019

Я решил использовать ловушки React для моего компонента, используя windom width и изменить размер прослушивателя событий.Проблема в том, что я не могу получить доступ к текущему значению, которое мне нужно.Я получаю вложенное значение, которое было установлено при добавлении прослушивателя событий.

Передача функции в функцию установки значений не является для меня решением, поскольку она вызывает рендеринг и нарушает другие мои функции.

Я прилагаю минималистичныйпример для представления основной проблемы:

import React, { Component, useState, useEffect } from 'react';
import { render } from 'react-dom';

const App = () => {
  const [width, setWidth] = useState(0);

  const resize = () => {
    console.log("width:", width); // it's always 0 even after many updates
    setWidth(window.innerWidth);
  };

  useEffect(() => {
    resize();
    window.addEventListener("resize", resize);
    return () => window.removeEventListener("resize", resize);
  }, []);

  return <div>{width}</div>;
}

render(<App />, document.getElementById('root'));

LIVE DEMO IS HERE

Пожалуйста, за помощью.

Ответы [ 2 ]

8 голосов
/ 24 марта 2019

При каждом рендере вы получаете новую копию функции resize.Каждая копия фиксирует текущее значение width.У вашего слушателя есть копия, которая была создана при первом рендере с width = 0.

. Чтобы исправить эту проблему, у вас есть несколько вариантов:

  1. Обновлять слушателей, когда widthизменения

    useEffect(() => {
      resize();
      window.addEventListener("resize", resize);
      return () => window.removeEventListener("resize", resize);
    }, [width]);
    
  2. Использование функциональных обновлений для получения текущей ширины внутри слушателя

    const resize = () => {
      setWidth(oldWidth => {
        console.log("width:", oldWidth);
        return window.innerWidth
      });
    };
    
  3. Сохранить ширинув изменяемой ссылке

    const widthRef = useRef(width);
    
    const resize = () => {
      console.log("width:", widthRef.current);
      widthRef.current = window.innerWidth;
      setWidth(window.innerWidth);
    };
    
0 голосов
/ 02 июля 2019

Другой способ получить данные - установить переменную из компонента

DEMO

import React, { Component, useState, useEffect } from 'react';
import { render } from 'react-dom';

//******* 
const appData = {
      width:0
}
//*******

const App = () => {
  const [width, setWidth] = useState(0);

  const resize = () => {
    //******* get width
    console.log('===>',appData.width);
    //*******

    console.log("width:", width); // it's always 0 even after many updates
    setWidth(window.innerWidth);
    //******* update width
    appData.width = window.innerWidth;
    //*******
  };

  useEffect(() => {
    resize();
    window.addEventListener("resize", resize);
    return () => window.removeEventListener("resize", resize);
  }, []);

  return <div>{width}</div>;
}

render(<App />, document.getElementById('root'));
...