Реагируйте, чтобы получить размер родительского элемента в ResponsiveReactGridLayout

#reactjs #typescript #react-hooks #react-grid-layout

Вопрос:

Я пытаюсь отобразить панель мониторинга с помощью ResponsiveReactGridLayout , и мой код в функциональном компоненте выглядит следующим образом:

 
const Home = () => {
  const [coins, setCoins] = useState(latestCoins);
  const [coin, setCoin] = useState(curCoin);
  const canvasRef = useRef(null);

  useEffect(() => {
    getCoins().then((data) => setCoins(data));
  }, []);
  return (
    <ResponsiveReactGridLayout
      onResize={(e) => console.log(e)}
      className="layout"
      layouts={layouts}
      rowHeight={100}
      breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
      cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
    >
     
      <div key="candlestick" className="home-card" ref={canvasRef}>
        {console.log(canvasRef)}
        //Trying to use canvasRef.current.width and height but getting an error: Property 'width' does not exist on type 'never'
        <Candlestick coin={coin} width={600} height={400} />
      </div>
    </ResponsiveReactGridLayout>
  );
};
 

Мой компонент подсвечника возвращает объект react-stockcharts ChartCanvas , для которого требуются ширина и высота (без которых он не занимает все пространство div).

Как я могу получить высоту и ширину из div?

Я пробовал использовать useRef() крючок, но он всегда кажется текущим как нулевой.

Могу я получить какую-нибудь помощь?

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

1. Пожалуйста, добавьте код useRef() вместе с описанием. Скорее всего, вы могли бы использовать его вне области действия react для обновления значений

2. @PushpikaWan, я обновил. Спасибо.

Ответ №1:

Свойство «ширина» не существует для типа «никогда»

На самом деле это ошибка машинописного текста. Это означает, что TypeScript не знает, каким .current должен быть тип свойства. Поэтому он не знает, что .current у него есть свойства .width , .height и это мешает вам получить к ним доступ. Вам нужно сообщить TypeScript, что это ссылка на a div .

На самом деле у An HTMLDivElement нет .width и .height , но вы можете использовать .clientWidth или .offsetWidth вместо этого.

 const canvasRef = useRef<HTMLDivElement>(null);
 

Я пробовал использовать крючок useRef (), но он всегда кажется текущим как нулевой.

ResponsiveReactGridLayout Компонент устанавливает свои собственные ссылки на своих дочерних элементах, поэтому ваш ref={canvasRef} файл перезаписывается.

Самый простой способ обойти это-добавить еще один слой вложенности. Ссылка ResponsiveReactGridLayout будет установлена на самой внешней div , но вы можете добавить еще div одну внутри нее с помощью ссылки, которую вы контролируете. Убедитесь, что он заполняет всю высоту.

Обратите внимание, что .current свойство все еще может быть null на первом рендеринге. Вы можете использовать значение по умолчанию, как предлагает @PushpikaWan, или вы можете отложить отображение диаграммы до тех пор, пока не получите фактическую ширину.

 <ResponsiveReactGridLayout /*...props...*/ >
    <div key="candlestick" className="box">
        <div ref={canvasRef} style={{ width: "100%", height: "100%" }}>
            {canvasRef.current ? (
                <Candlestick
                    data={data}
                    width={canvasRef.current.clientWidth}
                    height={canvasRef.current.offsetHeight}
                />
            ) : null}
        </div>
    </div>
    /*...other children...*/
</ResponsiveReactGridLayout>
 

Мне нужно было добавить явное width в макет сетки, чтобы заставить это работать. Я не уверен, что вы уже выполняете эту часть, но вы можете использовать WidthProvider , как описано в документах.

 import { Responsive, WidthProvider } from 'react-grid-layout';

const ResponsiveReactGridLayout = WidthProvider(Responsive);
 

Демо-версия CodeSandbox

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

1. Большое спасибо, Линда! Кажется, что добавление еще одного div с шириной на нем работает. Сейчас я попытаюсь выровнять его.

Ответ №2:

Вы можете получить его как неопределенный при начальной загрузке, пожалуйста, используйте этот необязательный оператор там

 canvasRef?.current?.width
 

Если у вас есть какое-либо значение по умолчанию, вы также можете использовать нулевое объединение со значением по умолчанию

 canvasRef?.current?.width?? default_value
 

тогда все будет так, как показано ниже

  <Candlestick coin={coin} width={canvasRef?.current?.width?? default_width} height={canvasRef?.current?.height ?? default_Height} />
 

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

1. К сожалению, это не сработало. Все еще видел ту же ошибку в Property 'width' does not exist on type 'never'.

2. @ShubhankarAgrawal это ошибка машинописного текста. Вам нужно использовать const canvasRef = useRef<HTMLDivElement>(null);

3. @LindaPaiste, спасибо, что поправил меня в этом, но я все еще вижу, что canvasRef.current всегда равен нулю.

4.Это всегда null или всегда null только при первом рендеринге? Я думаю, что это будет null сначала, а затем получит значение. Но tbh вы не используете onResize функцию, которая, вероятно, является лучшим методом. Я мог бы пойти обновить свой ответ.

5. @LindaPaiste, это всегда ноль, независимо от того, сколько раз я обновляю. Приношу извинения, я новичок в реагировании.