I have a use-case where I need to assign a unique and persistent unique id to each HTML tag in my page.
Background:
I have created a block element so everything in the webpage is a <Block />
element now.
The block element is defined like this
export const Block = ({ children, className = "", id = "", ...props }) => {
const handleClick = () => {
console.log("Clicks working");
};
const prevChildrenRef = useRef(children);
useEffect(() => {
if (prevChildrenRef.current !== children) {
console.log(`Content changed for id ${id}`);
prevChildrenRef.current = children;
}
}, [children, id]);
console.log(`Rendering Block with ID: ${id}`);
return (
<div className={`${className} hover`} id={id} onClick={handleClick} {...props}>
{children}
</div>
);
};
This is how I am using my block element, similarly in the whole page, everything is a Block at the atomic level.
usage:
<Block className="flex flex-col items-start space-y-1 text-start">
<Block>
<Block className="text-4xl font-bold">{start.name}</Block>
<Block className="py-2 text-2xl">{start.headline}</Block>
</Block>
</Block>
I would want to create a unique and persistent id for each block so even after page refresh, it would remain consistent.
What I have tried:
I tried naming every section’s block using recursion, so the top root element will have unique id as the section name, for example here, start, as we go down the children, they will be have the id <parent_id>_1, <parent_id>_2, <parent_id>_1_1 (parent’s grandchildren) and so on.
Here is the code.
export const assignIds = (element, idPrefix = prefix) => l{
let counter = 1;
const childrenWithIds = React.Children.map(element.props.children, (child) => {
if (React.isValidElement(child)) {
const newIdPrefix = `${idPrefix}_${counter}`;
counter++;
return React.cloneElement(
child,
{ id: newIdPrefix, key: newIdPrefix },
assignIds(child, newIdPrefix),
);
}
return child;
});
return React.cloneElement(element, { id: idPrefix }, childrenWithIds);
};
While this approach works, the issue I am facing is, when the value of {start.name} or {start.headline} is changed, I only want to capture the id of that block which it is under,and not the parent or grandparent. Right now with my code implementation, it is also triggering the console – console.log(`Content changed for id ${id}`); (in the block)
defined inside useEffect for parent as well as grandparents.
Where I need help
Ultimately, what I want is to capture the id of only the block which is being changed, without involving any ancestors so I can dynamically pass the CSS to change its style dynamically.