React useLayoutEffect
Problem to solved!
I need to deal with a problem that i need to grab the dimension of the component.
The core approach is to grab component width once re render fire, and apply side effect. which is getting the new dimension for the layout.
To handle this case, useEffect
pop out in my mind and i tried to find a way to get the dependency of the useEffect
useEffect(()=> {
// test effect
}, [])
Original Approach
Apply useRef
to desired component to get info of the element. call getBoundingClientRect
to grab the dimension of the element.
Once, i think of adding the logic directly inside to the code block. But for re-usability and better maintainability, its better to extract as a custom hooks.
This is the draft of the custom hooks:
const useDimension = () => {
const ref = useRef();
const [dimensions, setDimensions] = useState({});
useEffect(() => {
setDimensions(ref.current.getBoundingClientRect().toJSON());
}, [ref.current]);
return [ref, dimensions];
};
Dive Deep
When i dive deep for DOM related custom hooks. useLayoutEffect
jump out. The main Difference between useEffect and useLayoutEffect is
The time when the function fired
In ordinary click event handler. There is several stages to go through the repaint process
1. Button is clicked by the user
2. Click handler is fired
3. React update the state internally
4. React perform the DOM Mutation
5. Browser repaint the DOM change to the screen
useEffect
function is fried when the render is committed to the screen. which should be step 6
useLayoutEffect
function is fired after DOM mutation are computed. which is right after step 4
Rework
So for better DOM manipulation, useLayoutEffect is a better solution and I refine it as follow:
const useDimension = (trackCondition = []) => {
const ref = useRef();
const [dimensions, setDimensions] = useState({});
useLayoutEffect(() => {
setDimensions(ref.current.getBoundingClientRect().toJSON());
}, [...trackCondition, ref.current]);
return [ref, dimensions];
};
adding additional track Condition to grab component dimensions.