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

Hooks: Storing a React component as state produces an unintuitive error #14186

Closed
joepie91 opened this issue Nov 10, 2018 · 5 comments
Closed

Comments

@joepie91
Copy link

joepie91 commented Nov 10, 2018

Do you want to request a feature or report a bug?

Bug.

What is the current behavior?

Storing a function component as state using useState is interpreted as providing a lazy state function, and React then attempts to use the returned rendered result as a component.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

(Note: The context-related code is not relevant to this bug. I'm just reusing the same skeleton code for tracking down another bug that is context-related. But that one is probably a bug in my own code.)

What is the expected behavior?

React components - functional or otherwise - should be treated as state values rather than as lazy functions.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

16.7.0-alpha0. Earlier versions not applicable, since this is about hooks.

@Jessidhia
Copy link
Contributor

Jessidhia commented Nov 10, 2018

That is a known possible point of confusion with useState's ability to be lazy-initialized.

You probably want to use useCallback to memoize a function, component or not, but if you really want to put in a useState or useMemo, you need to return the function from the lazy initializer function. That is, useState(() => FunctionComponent) instead of useState(FunctionComponent).

@joepie91
Copy link
Author

Hrm, that seems like an ergonomics problem, given that useState is effectively doing double-duty, and in this case it's ambiguous what the developer actually intended.

I've run into a similar scenario before with the API design in one of my own projects, and there I eventually decided to just have separate foo and fooLazy methods, where only the latter accepted a lazy value producer function; that would make it explicit whether a function is intended to be used as a lazy producer, or whether the function is itself the value.

I'm not convinced that it's possible to merge eager and lazy usage into a single API without causing such issues. Perhaps React should make a similar distinction.

@Jessidhia
Copy link
Contributor

This is where using a type system would help you 😉

@gaearon
Copy link
Collaborator

gaearon commented Nov 11, 2018

You’re welcome to comment on the RFC if you have an alternative proposal. We’ll read all comments there.

Indeed this is an intentional decision even though we recognise the downsides.

@joepie91
Copy link
Author

I've posted a comment over there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants