DEV Community

Cover image for Measuring Text on React with Hooks
Danilo Assis
Danilo Assis

Posted on

12 4

Measuring Text on React with Hooks

Sometimes UI brings constraints that make development a little bit harder. This week at Entria I need to implement an array of labels that fills buttons.

The problem, simply, I need all buttons to have the same size because of the UI. Reading the React docs I found a simple way to implement this and I think should be a good idea shared with everyone.

So, just to situate us let's imagine that we need to implement a scale of buttons. And the labels of these buttons are dynamic, so the user can have any type of strings on this.

A good scale example can be: "does not meet", "partially meets", "meets", "surpasses".

That is, we have our array ["does not meet", "partially meets", "meets", "surpasses"]

Our component will receive these labels as array from our backend. Thinking our user in some scenarios will have a poor internet connection, we need to understand how to handle this case until we have the bigger text. So, I create a hook for this:

const [isCalculating, setIsCalculating] = useState<boolean>(true);

Until this hook will set as false, our component won't be rendered. After, we need to calculate the bigger text of all. At this point, we go to this react doc https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node.

Based on this, we will measure a DOM node and with our hook, we can know if this is already done or not.

If our hook isCalculating is true we will call a function to get the biggerText and set it on a DOM node (span tag).

if (isCalculating) {
const biggestText = getBiggerTextWidth();
return <span ref={measuredRef}>{biggestText}</span>;
}

The function's really easy and simple. I just got my array of labels and with a reduce I got the bigger text and return it.

const getBiggerTextWidth = () => {
return labels.reduce((acc, cur) => {
if (cur.length >= acc.length) {
return cur;
}
return acc;
}, '');
};

When returned, will be set on span that contains the react measure function example. I just add two things:

  • New hooks called setWidth setting the dom node width. We will use it later.

  • The hooks isCalculating setting as false.

const measuredRef = useCallback(node => {
if (node !== null) {
setWidth(node.getBoundingClientRect().width);
}
return setIsCalculating(false);
}, []);
view raw measuredRef.js hosted with ❤ by GitHub

Now, our component will check our hook, see it is false and returned our whole component with the scale of buttons.

type Props = {
labels: string[];
}
const ScaleButtons = ({labels}:Props) => {
const [isCalculating, setIsCalculating] = useState<boolean>(true);
const [width, setWidth] = useState<number>(0);
const measuredRef = useCallback(node => {
if (node !== null) {
setWidth(node.getBoundingClientRect().width);
}
return setIsCalculating(false);
}, []);
const getBiggerTextWidth = () => {
return labels.reduce((acc, cur) => {
if (cur.label.length >= acc.length) {
return cur.label;
}
return acc;
}, '');
};
if (isCalculating) {
const biggestText = getBiggerTextWidth();
return <span ref={measuredRef}>{biggestText}</span>;
}
const range = labels.length;
const renderLabel = (position: number) => {
return labels[position];
};
const renderButton = (position: number) => {
return (
<Button
key={position}
width={width}
>
{renderLabel(position)}
</Button>
);
};
return (
<Flex>
{range.map((_, index) => renderButton(index))}
</Flex>
);
}
view raw ScaleButtons.js hosted with ❤ by GitHub

Alt Text

So, if we have a case where the scale is bigger than width screen, we can handle easily with css flexbox:

Alt Text

Feel free to contact me to give advice about better ways to implement this or improves my English. My DMs on twitter is always open.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay