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
"Lazy initial state" is actually greedy #3338
Comments
Hmm good point. I think the intended part that was implied is that the computation is cached. I don't think "functional" describes that but you're right this is not exactly "lazy" either. |
We're gonna rewrite those parts anyway (#3308) so we'll do that change there. |
Brainstorming time if you haven't decided on the final version yet:
|
The "lazy ref init" pattern uses the same terminology so if we decide to use another term we should look at every usage of "lazy" in the docs. I always understood lazy as in "called when actually needed". For useState that means it won't be called on updates because we definitely are going to throw away the result. As opposed to So for me I do consider the state lazy. That lazy init just happens to be needed sync on mount. On updates React is actually lazy and just ignores it. If you look at "lazy initialization" on google:
-- https://en.wikipedia.org/wiki/Lazy_initialization As I interpret the React docs the term is fitting. Though we should always make an effort to explain terms. |
@eps1lon hm, good point, but I don't think this feature was intended for actual lazy data structures in the sense you quote: const [value] = useState(function*() { let n=0; while(true) yield n++ })
console.log(value.next()) I would probably define the generator outside of React, initialize the iterator in The documentation that you point to supports my point (if I may interpret it charitably):
So the FTR: Following is already "lazy" in this sense because a Component is a function that is not executed immediately, but only when actually rendered (and we don't call them Lazy Initialized Components): function Component() {
const connection = getConnection() // initialized on first render and cached later, nothing to do with useState
const [value, setValue] = useState(connetion)
} |
to clarify: |
And to be crystal clear whether we are on the same page in understanding of "lazy" from the quoted C++ article: // Initialize by using default Lazy<T> constructor. The
// Orders array itself is not created yet.
Lazy<Orders> _orders = new Lazy<Orders>();
// We need to create the array only if displayOrders is true
if (displayOrders == true)
{
DisplayOrders(_orders.Value.OrderData);
} That is not how useState function argument works: const [value, setValue] = useState(() => ({orderData: 'data'))
// value.orderData already exists on the above line, React does NOT defer evaluation until the line below
if (displayOrders === true) {
console.log(value.orderData)
} |
It couldn't know this without an actual compiler. As soon as the state is declared it is considered "used". But I understand how this is an overly technical explanation. I would still caution against changing the term because it might make perfect sense right now to some people (though I am biased here because it makes sense to me). I'd rather explain the term in the context of React. The docs already use a bunch of terms that aren't technically correct in every instance (pure, side-effect free, memoization). |
I'm with @eps1lon. Specifically:
But I also understand the problem that @Aprillion mentions. Maybe we can call it something like |
Is there any good reason to call the
useState(() => ...)
feature "Lazy initial state"? The actual implementation is synchronous ("greedy") as far as I can tell, so I would propose to rename it to "Functional initial state" (for consistency with "Functional updates").Related "Lazy initialization" in useReducer section => I would propose "Initialization function"
I can make a PR unless someone points out some aspect of the naming that I missed.
The text was updated successfully, but these errors were encountered: