hookstate
hookstate copied to clipboard
Add on State.get() check and error to the console (WAS: StateMethods.merge does not detected recursive Proxy wrapping.)
I am using React-Select (https://react-select.com/home), where the way of updating the state is to give all values at once (instead of giving just the newly added element and use state.merge())
I see that when you call .get() the state is wrapped around some kind of Proxy element? (It says Proxy in Console when I print the object) So that whenever I get a new element, all the old elements get wrapped around a new Proxy element. This nesting continues until I get a "Uncaught RangeError: Maximum call stack size exceeded" error.
Is there a way to unwrap these Proxy elements before I set the state?
Did this make sense? :P
Also, I'm loving hookstate! Keep up the good work :D Definitely going to use this for all my future projects!
doing () => {state.get()} solved this somehow :shrug:
also state.get().anything worked ???
Sorry, I do not understand what your problem is. It looks like you ended up with nested states set to values of state object. 'set' method traps it and should raise this exception: https://hookstate.js.org/docs/exceptions#hookstate-102 Maybe merge method misses this checking, I will have a look.
Is there a way to unwrap these Proxy elements before I set the state?
If you give me more complete example of what you are doing, I might answer your question.
where the way of updating the state is to give all values at once (instead of giving just the newly added element and use state.merge()
To set the value at once, use this: https://hookstate.js.org/docs/typedoc-hookstate-core#set You can learn more details here: https://hookstate.js.org/docs/nested-state#advanced-mutations-for-an-object-state
please, note: state.get() also returns a proxy for object values. So I need to see more details of what you are doing, to help you. Maybe you can publish reproducer project?
Also, I'm loving hookstate! Keep up the good work :D Definitely going to use this for all my future projects!
Thanks. Could you please help the project to grow by spreading few words about in blogs and communities? Thanks
Reopen to keep it as a reminder to have a look how to prevent recursive proxy wrapping in merge method.
I did a bad job at explaining :P
export default function SelectPage() {
const selectedOptions = useState([]);
const handleChange = option => {
//Option are all the options selected so far, and not just the newly selected option
selectedOptions.set(option);
}
return (
<Select
value={selectedOptions.get()}
onChange={handleChange}
/>
);
}
Selecting the first option works fine. We get [Proxy{option1}], however when selecting the next option i get the error "Uncaught RangeError: Maximum call stack size exceeded". This is because selectedOptions is now [Proxy{Proxy{option1}},Proxy{option2}]
This fixes the problem:
value= {selectedOptions.get().anything}
as i found from here https://stackoverflow.com/questions/51096547/how-to-get-the-target-of-a-javascript-proxy
Maybe it would be nice with a function like selectedOptions.getUnwrapped()?
Im on Hookstate 3.0.0 btw
Ok. Do this: const selectedOptions = useState([]).attach(Downgraded); It will help to disable proxy returning from selectedOptions.get(). The complete example would be:
export default function SelectPage() {
const selectedOptions = useState([]).attach(Downgraded);
const handleChange = option => {
//Option are all the options selected so far, and not just the newly selected option
selectedOptions.set(option);
}
return (
<Select
value={selectedOptions.get()}
onChange={handleChange}
/>
);
}
Anybody still facing this you can use selectedOptions.get({noproxy:true}), it will give plain objects rather than wrapped in proxy.