In the first example, the buttons are dynamically created from an array.
RonBonBon opened this issue · comments
In the first example, the buttons are dynamically created from an array.
Every time a button is pressed, it changes some local state, which causes a re-render and that causes the buttons to be re-created.
See console output in example link,
CodeSandbox : https://codesandbox.io/s/leva-test-1-c1omd2?file=/src/App.jsx
This is pretty obvious to the expert eye why the buttons are being recreated when the state changes.
So, if I try to memoize the creation of the buttons. it works as intended and doesn't recreate the buttons every time the local state changes.
const buttons = {}
useMemo(() => {
positions.forEach((p, i) => {
console.log('creating button ' + i)
buttons['button ' + i] = button(() => {
setTo(p)
})
})
}, [positions])
useControls('Camera', buttons)
However, there is now the react warning "react-hooks/exhaustive-deps", despite my example now working as intended.
See console output in example 2 link : https://codesandbox.io/s/leva-test-2-mj1d09?file=/src/App.jsx
In the example 2 link, the buttons are being created only once, even when you change the local state. Perfect, except for the warnings.
So then to solve the react-hooks/exhaustive-deps
warning, I add the extra dependency to the useMemo
hook.
const buttons = {}
useMemo(() => {
positions.forEach((p, i) => {
console.log('creating button ' + i)
buttons['button ' + i] = button(() => {
setTo(p)
})
})
}, [positions, buttons])
And then I get a different react-hooks/exhaustive-deps
warning saying to wrap the initialization of 'buttons' in its own useMemo()
Hook.
CodeSandbox Example 3 : https://codesandbox.io/s/leva-test-3-xyjcjc?file=/src/App.jsx
Ok, so then I do it,
const buttons = useMemo(() => {}, [])
useMemo(() => {
positions.forEach((p, i) => {
console.log('creating button ' + i)
buttons['button ' + i] = button(() => {
setTo(p)
})
})
}, [positions, buttons])
Codesandbox : https://codesandbox.io/s/leva-test-4-lmhpey?file=/src/App.jsx
So, all warnings are now gone, but if I run it, then I get TypeError Cannot set properties of undefined (setting 'button 0')
I have tried all kinds of combinations to try and get this small demo to not recreate the buttons each time the state changes while also not having the react-hooks/exhaustive-deps
warnings.
I'm sure the answer is there, but I'm just unable to see it.
Originally posted by @Sean-Bradley in #393
It seems you have created a new issue from an issue that was already solved and closed.
#393 (comment)
Your problem is unclear because this is a verbatim copy of just one of the comments from the original thread.