Reputation: 10607
const [x, setX] = useState();
const [y, setY] = useState();
const elementRef = useRef(null);
// Calculated here based on elementRef (null on initial render, non-null after mount)
let boundTop;
let boundRight;
let boundBottom;
let boundLeft;
// Center the stage on mount and ref mount
useEffect(() => {
const x = (window.innerWidth / 2) - ((boundRight - boundLeft) / 2);
const y = (window.innerHeight / 2) - ((boundBottom - boundTop) / 2);
setX(x);
setY(y);
}, [elementRef.current]);
This code works fine and as intended - on initial render and ref mount ([elementRef.current]
dependency array), it will set the state of X and Y to some initial values and then never execute again.
But! The default Hooks ESLint rules nudge me to add the bound
state variables as dependencies to the useEffect
dependency array. I don't wanna do that! I don't want those values to change again through this hook after the initial mount.
If I did add the bound values as dependencies to the effect, my canvas could never move, because each move to it (by changing X and Y in response to mouse/touch) would cause a render, thus bounds would be recalculated, the hook dependencies changed, X and Y centered and the original movement of X and Y which caused the canvas to move would become undone.
Is there a pattern to use to code around this ESLint rule?
Upvotes: 1
Views: 873
Reputation: 7033
The useState
allows you to set its initial value via a callback, so you don't need your useEffect
at all.
Change your useState
like so and remove your whole useEffect
:
const [x, setX] = useState(() => (window.innerWidth / 2) - ((boundRight - boundLeft) / 2));
const [y, setY] = useState(() => (window.innerHeight / 2) - ((boundBottom - boundTop) / 2));
Upvotes: 2