Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add on State.get() check and error to the console (WAS: StateMethods.merge does not detected recursive Proxy wrapping.) #89

Open
98mux opened this issue Jul 15, 2020 · 8 comments
Labels
enhancement New feature or request hookstate-4 Marks issues which are solved starting from version 4. hookstate-5 Features postponed for v5

Comments

@98mux
Copy link

98mux commented Jul 15, 2020

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!

@98mux
Copy link
Author

98mux commented Jul 15, 2020

doing () => {state.get()} solved this somehow 🤷

also state.get().anything worked ???

@98mux 98mux closed this as completed Jul 15, 2020
@avkonst
Copy link
Owner

avkonst commented Jul 15, 2020

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

@avkonst
Copy link
Owner

avkonst commented Jul 15, 2020

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?

@avkonst
Copy link
Owner

avkonst commented Jul 15, 2020

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

@avkonst avkonst changed the title Updating the entire state instead of state.merge StateMethods.merge does not detected recursive Proxy wrapping. Jul 15, 2020
@avkonst avkonst reopened this Jul 15, 2020
@avkonst
Copy link
Owner

avkonst commented Jul 15, 2020

Reopen to keep it as a reminder to have a look how to prevent recursive proxy wrapping in merge method.

@avkonst avkonst added the enhancement New feature or request label Jul 15, 2020
@98mux
Copy link
Author

98mux commented Jul 16, 2020

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

@avkonst
Copy link
Owner

avkonst commented Jul 16, 2020

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}
/>
);
}

@avkonst avkonst changed the title StateMethods.merge does not detected recursive Proxy wrapping. Add on State.get() check and error to the console (WAS: StateMethods.merge does not detected recursive Proxy wrapping.) May 28, 2022
@avkonst avkonst added the hookstate-4 Marks issues which are solved starting from version 4. label May 28, 2022
@avkonst avkonst added the hookstate-5 Features postponed for v5 label Dec 18, 2022
@ankitsinghh121
Copy link

Anybody still facing this you can use selectedOptions.get({noproxy:true}), it will give plain objects rather than wrapped in proxy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hookstate-4 Marks issues which are solved starting from version 4. hookstate-5 Features postponed for v5
Projects
None yet
Development

No branches or pull requests

3 participants