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
GeneralStore@3.0.0 with hooks #64
Conversation
e1d833e
to
0b9ca53
Compare
🔥🤩 so so good! so so exciting! It's so interesting to look back on the evolution of the connect family, and be able to how the react apis / conventions of the time come out in these APIs. Obviously there's a lot of internal HubSpot context I've missed out on in the last year+. If you have the time to elaborate, I'm interested to learn some specifics for the sake of reflection/learning.
For the sake of discussion, I'd love to see one or two examples of what you imagine new usage patterns might look like!
It's clear that
BYYYEEEEEEEE 👋🎉
I haven't worked with typescript enough to know what you mean. Would you mind going into what specifically becomes possible in Typescript? I trust you I'm just curious. |
I'd be curious too. While there's a lot to love with TS and is very likely a better choice going forward for many reasons, the power of the type system is rarely where I'd expect TS to be a slam dunk when comparing the two. |
@colbyr stack order for answering these questions:
The biggest advantage we have now (which I didn't do yet but will do in a separate PR - wanted to avoid too much churn here) is TypeScript can express the relationship between two types, so
which would allow us to verify that the resultant object has the same keys as the dependency map and makes accessing those values typesafe. I couldn't find a way to do that in Flow (although my Flow experience is much more limited so maybe I just couldn't find the right construct). Either way I think the larger community built around TS will also be an advantage - more resources present and better tooling exists for TS than Flow in my experience. I also kept running into issues using Flow with hooks. The types for hooks were behaving very weirdly and didn't play well with refs at all. I was unable to type refs well so I ended up having to just use
No specific problems, but we ran into a few different cases where state had to be lifted into a wrapper component because we needed a local state value in a
The biggest place where we can simplify a ton of logic is customizing columns in the index pages. Currently we use |
There are various utility types with Flow to handle these cases. They're just poorly documented but some (not all!) are here. While there are a few things TS can do that Flow can't, it's usually the other way around. The community size and ease of use is really the argument for TS. |
Fair enough. Maybe just didn't do enough digging to get that dependent types code working properly. Regardless, still also had problems typing hooks properly (although that's something that might've been solved better by those utility types had I known about them before the migration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a8659c4 looks really clean 👍
Yeah today's flow has a lot more utility types than were available at the time most of this code was written. This was also the first real flow I ever wrote so there was some learning going on 🙃 I like flow, but I think the most important thing moving forward is that the folks maintaining this can understand the type checker. If y'all are in on TypeScript, do it 👍
Word 👌
That's a pretty compelling use case. One thing I'd encourage you to look into is what happens when a component has two+ separate hook dependencies on the same store.
I'm not sure it's very explicit in the code but because I haven't kept super-up-to-date on fiber/hooks stuff, but naively I could imagine the example above might cause the component to re-render 2 times in rapid succession. It could also be that that isn't a big deal. You'd probably know better than me at this point 😜 |
TypeScript is what's coming next in the pipeline internally, so I think that's what our teams will be comfortable with moving forward, which will inevitably come in handy if I'm not here to maintain this anymore :) I did look into re-renders of multiple subscriptions. Here we actually benefit from React batching I did just realize, however, that on each state transition here we're re-rendering the component even if the |
the hook has been renamed to |
Nice! I like when react does stuff for you 👌 LGTM |
under the advisement of @Phoenixmatrix I migrated the build to Rollup. it produces better output, and shaves about 5kb off the minified bundle (down to about 20kb now). @henryqdineen mind taking a look at the rollup config? I largely copied from existing configs in some of the bender repackages, but wanna make sure I'm not doing anything super wrong here. if all seems to be good with the build we should be good to ship this tomorrow/wednesday |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@colbyr looking to merge/publish this today. would you be able to add npm user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rollup config looks 👍
Have you considered enabling Locally I get these warnings:
|
hm. i thought i did have it enabled, guess not. i'll update that now |
@aem done 👍 |
|
||
const newValue = calculate(dependency, props); | ||
if (newValue !== dependencyValue) { | ||
setDependencyValue(newValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this be setDependencyValue(calculate(dependency, props));
because of https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately not. it causes an infinite loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok interesting. hooks are confusing!
gonna squash some commits to make the history a lil more sane |
remove bower, update changelog, add new docs useStore -> useStoreDependency only trigger state transitions when state calculation changes enable lint rules (facepalm), shallow equal, fix unnecessary dispatch bindings fix deps array
add bundled outputs for commonjs and esm remove unnecessary config rules from module bundles single output since it doesnt need to be dynamic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an RFC / initial implementation of GeneralStore@3.0.0. The library will now fully support
react@16
by adding a hooks-based api (GeneralStore#useStoreDependency
).useStoreDependency
only supports a single dependency, no compound dependencies, because the need for compound dependencies is gone. Whereas in older versions of GeneralStore users may have been required to pass multiple stores intoconnect
to obtain all of the information required to render a component, users aren't limited in any way around how props can be passed intouseStoreDependency
so previous limitations around props, passing values between storederef
s, or not being able to use local state don't exist at all. Instead, the new implementation allows us to use multiple stores independently, memoize the results of particular store calls, and pass arbitrary maps of props instead of needing to use the props of the current component as the props to thederef
.Upgrade Notes
react@^16.8
. With the introduction of the hooks-based API, it's not safe to use new versions of GeneralStore with older versions of React. If you're using React <=16.8.0
please useGeneralStore@2.5.1
or below.GeneralStore@3
is written in TypeScript. The existing codebase, while compatible with the existing version of Flow andreact@15
, didn't work well with modern versions of Flow and React. Additionally, Flow's type system isn't refined enough to safely express the complex type relationships between all of the components in this library. TypeScript, on the other hand, has a more robust type system that allows us to be more confident in the code we ship with this library. The commits in this pull request were structured in a way that maintains git history and should be merged as a merge commit rather than a squashed commit to maintain that history.GeneralStore@2.x
APIs:StoreDependencyMixin
connectWithState
useStoreDependency
trivially this API is unneeded and can be removed as well.bower.json
and relevant references.bower
has been in maintenance mode for some time and it doesn't make sense to keep maintaining the library on the outdated package manager.Example Usage
@colbyr