最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Get width from responsive React element during first render? - Stack Overflow

programmeradmin1浏览0评论

I have a React ponent named ResultList that is responsible for displaying products in a gallery.

But in order to choose the correct quantitity of products per row, I need to know how many pixels were left for my ponent, because there is some other logic that will determine if a side bar and a filter bar will appear together with the ResultList or not. Hence, the width of ResultList is responsive and it varies.

I've built this code to get the width of the element, but right now it doesn't work for the first render. And I don't know if that would be possible, because the element hasn't been created yet and the ref has not been assigned to anything. But how can I choose how many products to display on first render if I'm not able to know how wide my element is going to be?

See GIF below:

my ResultList would be the Item2

QUESTION

How can I get the width of Item2 during first render, and if that's not possible how can I hide it until I know what is the available width for it? Is there a better way to get the width of a responsive element than with window.getComputedStyle ?

CodeSandbox Link:

Full Code:

import React, { useRef, useState } from "react";
import ReactDOM from "react-dom";
import styled from "styled-ponents";

const S = {};

S.Container_DIV = styled.div`
  display: flex;
  height: 150px;
`;

S.FlexItem1 = styled.div`
  flex: 0 0 200px;
  background-color: lightblue;
`;

S.FlexItem2 = styled.div`
  flex: 1 1 80%;
  background-color: lightcoral;
`;

S.FlexItem3 = styled.div`
  flex: 0 0 160px;
  background-color: lightgreen;
`;

function App() {
  const itemRef = useRef(null);
  const [boolean, setBoolean] = useState(false);
  return (
    <React.Fragment>
      <S.Container_DIV>
        <S.FlexItem1>Item 1</S.FlexItem1>
        <S.FlexItem2 ref={itemRef}>Item 2</S.FlexItem2>
        <S.FlexItem3>Item 3</S.FlexItem3>
      </S.Container_DIV>
      <div>
        <br />
        Item2 width is:{" "}
        {itemRef.current && window.getComputedStyle(itemRef.current).width}
      </div>
      <div>
        <button onClick={() => setBoolean(prevState => !prevState)}>
          Force Update
        </button>
      </div>
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I have a React ponent named ResultList that is responsible for displaying products in a gallery.

But in order to choose the correct quantitity of products per row, I need to know how many pixels were left for my ponent, because there is some other logic that will determine if a side bar and a filter bar will appear together with the ResultList or not. Hence, the width of ResultList is responsive and it varies.

I've built this code to get the width of the element, but right now it doesn't work for the first render. And I don't know if that would be possible, because the element hasn't been created yet and the ref has not been assigned to anything. But how can I choose how many products to display on first render if I'm not able to know how wide my element is going to be?

See GIF below:

my ResultList would be the Item2

QUESTION

How can I get the width of Item2 during first render, and if that's not possible how can I hide it until I know what is the available width for it? Is there a better way to get the width of a responsive element than with window.getComputedStyle ?

CodeSandbox Link:

https://codesandbox.io/s/wizardly-blackburn-f1p7j

Full Code:

import React, { useRef, useState } from "react";
import ReactDOM from "react-dom";
import styled from "styled-ponents";

const S = {};

S.Container_DIV = styled.div`
  display: flex;
  height: 150px;
`;

S.FlexItem1 = styled.div`
  flex: 0 0 200px;
  background-color: lightblue;
`;

S.FlexItem2 = styled.div`
  flex: 1 1 80%;
  background-color: lightcoral;
`;

S.FlexItem3 = styled.div`
  flex: 0 0 160px;
  background-color: lightgreen;
`;

function App() {
  const itemRef = useRef(null);
  const [boolean, setBoolean] = useState(false);
  return (
    <React.Fragment>
      <S.Container_DIV>
        <S.FlexItem1>Item 1</S.FlexItem1>
        <S.FlexItem2 ref={itemRef}>Item 2</S.FlexItem2>
        <S.FlexItem3>Item 3</S.FlexItem3>
      </S.Container_DIV>
      <div>
        <br />
        Item2 width is:{" "}
        {itemRef.current && window.getComputedStyle(itemRef.current).width}
      </div>
      <div>
        <button onClick={() => setBoolean(prevState => !prevState)}>
          Force Update
        </button>
      </div>
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Share Improve this question asked Jul 15, 2019 at 15:42 cbdevelopercbdeveloper 31.6k45 gold badges202 silver badges397 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

To wait until the elements have rendered and thus the ref has a value you'll need to use an effect. useEffect kind of works, but you'll see a flicker of it rendering once before you recalculate. Instead, this is a case where useLayoutEffect can be used. It will render once, then you do your measurement and set state, then it will synchronously render again so no flicker should be seen.

function App() {
  const itemRef = useRef(null);
  const [itemWidth, setItemWidth] = useState(-1);
  const [boolean, setBoolean] = useState(false);
  useLayoutEffect(() => {
   // I don't think it can be null at this point, but better safe than sorry
    if (itemRef.current) {
       setItemWidth(window.getComputedStyle(itemRef.current).width);
    }
  });
  return (
    <React.Fragment>
      <S.Container_DIV>
        <S.FlexItem1>Item 1</S.FlexItem1>
        <S.FlexItem2 ref={itemRef}>Item 2</S.FlexItem2>
        <S.FlexItem3>Item 3</S.FlexItem3>
      </S.Container_DIV>
      <div>
        <br />
        Item2 width is: {itemWidth}
      </div>
      <div>
        <button onClick={() => setBoolean(prevState => !prevState)}>
          Force Update
        </button>
      </div>
    </React.Fragment>
  );
}

发布评论

评论列表(0)

  1. 暂无评论