21 ms·
> I don't want to learn magic that I don't understand without reading the documentation (useState, createSignal et al). Really now. Most devs who think to them
by chmod775 2y ago
> I don't want to learn magic that I don't understand without reading the documentation (useState, createSignal et al).
Really now. Most devs who think to themselves "man I wonder how useState works internally" will arrive at the logical and correct answer within seconds. It's not complicated or magic. There are bare-bones implementations of react hooks (-ish) with a couple hundred lines of code. Implementing a basic "useState" and "runFunctionComponent" is easier than most third-semester CS assignments.
If that's the bar for magic, I'm surrounded by 20th level Warlocks coming up with new Eldritch Invocations for fun over breakfast.
- zelphirkalt 2y agoHundreds of lines of code?? That sounds like way too much complication for something like that, tbh.
- chmod775 2y agoIf you want to be at least sort-of react hooks compatible, there's a bunch of hooks you need to implement.
- kaba0 2y agoHeh? My smallest hobby project that is not a POC but actually is finished and is doing something is like 1000 lines long. There are very few stuff you can do with less than 100 lines. (Just for completeness sake, Haskell and alia sometimes might get away with less lines, because they tend to be “wider”. Word-count is a better metric here)
- imtringued 2y ago>Most devs who think to themselves "man I wonder how useState works internally" will arrive at the logical and correct answer within seconds. The answer is shockingly dumb. To be fair, I checked the code years ago, but basically almost every hook calls useReducer internally and useReducer uses an array stored in a global variable that is set before your component code gets called and the order of the hook calls determines which hook gets what useReducer state. It's basically a giant kludge and the React developers and users pat themselves on the back how "functional" their components are, when in reality they are flinging global mutable state like crazy.
- chmod775 2y ago> It's basically a giant kludge and the React developers and users pat themselves on the back how "functional" their components are, when in reality they are flinging global mutable state like crazy. This is true for literally every useful computer program ever. At some level it operates exclusively on global mutable state. Doesn't mean your high level programmer-facing interface has to look like that though.
- kaba0 2y agoHaskell compiles down to a C “subset” called C-, and flings mutable state and memory like crazy. That’s the whole point of encapsulation, if the abstraction is sound then it absolutely doesn’t matter that react uses global state — like how else would they do it with this user ergonomics? Using JS is a given.
- spion 2y ago> Implementing a basic "useState" and "runFunctionComponent" is easier than most third-semester CS assignments. I'm not sure it is. There is a global dispatcher that finds the right component state to use and increments a counter to ensure that the correct state "slot" for that component is used. There are also a bunch of mechanisms to prevent slot mismatches. I guess you could make a loose analogy with writing custom allocators, except instead of the binding knowing the address, the order of calling useState determines the address :) Really not that simple.
- chmod775 2y ago> I'm not sure it is. There is a global dispatcher that finds the right component state to use and increments a counter to ensure that the correct state "slot" for that component is used. Explicitly not part of that proposed task. We're talking about a basic hooks implementation with useState here, not how react deals with its tree of components. For the sake of the task the signature of runFunctionComponent just needs to be runFunctionComponent<P, R>(fc: (props: P) => R, props: P, hooks?: any[]): { hooks: any[], returnValue: R } or even dumbed down to runWithHooks(runFC: () => void, hooks?: any[]): any[] where runFC would wrap the call to the function component to pass the appropriate props and store the return value, freeing students from thinking about that. Also specify the function doesn't need to be re-entrant. In either case it won't need concern itself with what the component returns (children, whatever), matching children to tree nodes, or scheduling, at all. Would be nonsense to cram that logic in there anyhow. What you were talking about would make a good later task: easy to get a basic implementation, but hard to get an implementation that isn't subtly wrong in some way. Plus you can slap on extra goals like supporting keys. Lots of room to score students beyond just pass/fail.