leva
leva copied to clipboard
useControls() hook dependencies do not cause reevaluation of return values
With the given settings I am passing, at no point does the react hook property dependency cause the shadows value to be updated. I've hacked around and copied the dependency list to addition args, but it made no difference.
// "leva": "^0.10.0"
const { isTouchDevice } = useDeviceDetection()
const { shadows } = useControls(
'Stage',
{
shadows: !isTouchDevice,
},
[isTouchDevice],
)
Am I missing something?
Primitive dependencies aren't passed by reference, so the parseArgs has no effect in my case.
e.g.
const {
folderName,
schema,
folderSettings,
hookSettings,
deps
} = parseArgs(schemaOrFolderName, settingsOrDepsOrSchema, depsOrSettingsOrFolderSettings, depsOrSettings, depsOrUndefined);
console.log('For ', folderName, ' deps are ', deps);
Results in:
Attempting to use an object instead of primitive also does not work.
Perhaps simplifying the method signature or signatures, providing different hook entries makes sense here? React hooks appear to disallow overloaded signatures.
It appears that use of an object for deps is triggering a call to folder() with updated schema, but the UI component does not change, and the return value from useControl does not change.
const _schema = useDeepMemo(() => {
depsChanged.current = true;
const s = typeof schema === 'function' ? schema() : schema;
console.log('useDeepMemo called for a recalc for ', folderName, ' folderSettings: ', folderSettings, ' schema: ', s);
return folderName ? {
[folderName]: folder(s, folderSettings)
} : s;
}, deps);
I believe this is by design. The deps will allow you to update the schema when they change, but the return values of the controls are driven by the state of the control in leva.
If you would like to update the value of a control directly you need to follow this pattern using the set function to update the state of the control. When you use a function to initialize your schema, the useControls hook behaves like a useState hook.
const [{entities}, setStats] = useControls('Stats', () => {
return {
entities: {
value: '',
label: 'entities',
editable: false,
},
};
});
useEffect(() => {
setStats({
entities: entities.length.toFixed(0),
});
}, [entities, setStats]);
The above is correct, values are not updated via dependencies, only the controls themselves are - removing, adding- etc. @thejustinwalsh has the right solution for this use-case. Please reopen if there's more to it!