jaydenseric / graphql-react

A GraphQL client for React using modern context and hooks APIs that is lightweight (< 4 kB) but powerful; the first Relay and Apollo alternative with server side rendering.
https://npm.im/graphql-react
MIT License
717 stars 22 forks source link

New composable React hooks #53

Closed jaydenseric closed 3 years ago

jaydenseric commented 4 years ago

Currently, the useGraphQL React hook does a lot, which is not desirable for a few reasons:

  1. It's hard to test. With so many options interacting with each other, every option variation needs to be tested with most of the variations of the other options.
  2. Options have a performance cost regardless if they are being used. For example, the loadOnReset option utilizes a React.useCallback and a React.useEffect:

    https://github.com/jaydenseric/graphql-react/blob/d87d3b3d95930a09922d9c009b47bd78bb2ff488/src/universal/useGraphQL.js#L203-L229

  3. The code supporting options increases the bundle size, regardless if the options are even being used.
  4. If a consumer wants to subscribe to the GraphQL events for their own custom purposes using React.useEffect (e.g. to do something in a callback if cache is reloaded while the component is mounted) they have to reinvent wheels that are already implemented inside useGraphQL.

I won't be sure of the final design for the hooks without a lot of work that might also depend on some big changes to the GraphQL client API as well as the SSR API, but here is one idea:

const onGraphQLReset = React.useCallback(
  ({ exceptCacheKey }) => {
    if (cacheKey !== exceptCacheKey) load();
  },
  [load]
);

useOnGraphQLReset(onGraphQLReset);
jaydenseric commented 4 years ago

I've also got some ideas about a new approach to SSR that could be abstracted into a separate published package:

const { isSSR, rerenderAfter } = useSSR();

if (isSSR && !cacheValue) {
  rerenderAfter(load());
  return null;
}
jaydenseric commented 3 years ago

I've been working full time on a brand new graphql-react API and about 80% of the work is complete. It's really taking shape! It's much more intuitive, efficient, has a smaller bundle size, and is user extensible; the cache could potentially be used for more than just GraphQL and loading could potentially be done via custom hooks using something other than fetch.

Very excited to introduce it some time in the next few weeks, assuming everything works as well as expected in my own apps.

My only concern is that more separate, focused, hooks might result in more renders, but hopefully not.