HNHacker News
TopNewBestAskShowJobs

davidmccabe

50 karma · joined May 14, 2020

UI Engineer, React team at Meta. Previously, author of Recoil (http://recoiljs.org). Open to network.
submissionscomments
davidmccabe··on Tuql: Automatically create a GraphQL server from a SQLite database
GraphQL is really intended to model UI concepts rather than directly exposing your database schema.

First of all, your GraphQL schema is basically append-only due to older clients that may remain in the wild. So you don't want to expose implementation details that may change.

Second, you want to write client code that handles mutations. This is easier if the data the client receives is organized in a UI-centric way. I'll give you a simple example that came up at work recently: a single conceptual category (a "user account") that, due to implementation details, was spread across two different tables with different columns. Because the GraphQL schema in this case mapped each table to its own GraphQL type, somebody was then able to write client code that only handled one type and not the other, causing an inconsistent UI.

I would suggest thinking carefully about your GraphQL schema, treating it as an API, and not auto-generating it. Of course, you want it to be convenient to construct, just not fully automatic and thoughtless.

davidmccabe··on New Official Relay Tutorial
Hey, this is David from the React team at Meta. I've been working on revamped documentation for Relay, our GraphQL data fetching library. Relay is an incredible technology but has been virtually undocumented up until now. This tutorial covering the basics is just a down payment on improving matters. Looking forward to your feedback!
davidmccabe··on Recoil – A state management library for React
We are planning in the next few weeks an overhauled persistence API. Among other things this will add the ability to provide a callback in `initializeState` rather than a value. However, this doesn't help if you need to do async work to retrieve the value. The way we generally think of SSR is that you get a single render pass and then you're done, no time for async work. So for hitting a database you want something like Relay that statically knows your data dependencies and can do a single request to initialize. It's true that there's some complexity there, but there are also great solutions to really hard problems. Recoil doesn't attempt to address that space.
davidmccabe··on Recoil – A state management library for React
React doesn't have to commit to the DOM if there are no changes, but it still has to render each component and compare the output. Even if the component is memoized, it still has to compare the props. This is fast enough most of the time but it can become a bottleneck in some cases.
davidmccabe··on Recoil – A state management library for React
I could be mistaken but I think that you still have to do a shallow compare on the connected props of every component.
davidmccabe··on Recoil – A state management library for React
Well, I should say "doesn't make it harder". The `RecoilRoot` component accepts a prop called `initializeState` that lets you specify the state of all atoms in the initial render.
davidmccabe··on Recoil – A state management library for React
For a specific set of atoms you could subscribe to them with a component and then use an effect to send the values out. For all atoms you could use useTransactionObservation.
davidmccabe··on Recoil – A state management library for React
It’s actually designed to make server rendering easy. We’ll add a guide about this eventually. Atoms aren't global singletons: their values are scoped to React trees.
davidmccabe··on Recoil – A state management library for React
The term 'atom' is a clojure-ism, that's where both I and reframe get it from.
davidmccabe··on Recoil – A state management library for React
If you update multiple atoms within a React batch, they will be updated at the same time, just as with React local state. You don't need to wrap the changes in anything to have them occur together.

In other words, this updates both of the atoms together:

  const [a, setA] = useRecoilState(atomA);
  const [b, setB] = useRecoilState(atomB);
  ...
  onClick={() => {
    setA(a => a + 1);
    setB(b => b + 1);
  }}

If the new values of multiple atoms are interdependent on each others' current values, it's possible to update multiple atoms together using the transactional/updater/function form, but we need to add a nicer interface for doing this. Coming soon! The nicer interface would probably look something like this:

  const update = useTransactionalUpdate([atomA, atomB]);
  ...
  onClick={() => {
    update(([a, b]) => [a + b, b - a]);
  }}
It's then easy to make a hook that provides a reducer-style interface over a set of atoms. But now, unlike with Redux or useReducer, each atom still has its own individual subscriptions!
davidmccabe··on Recoil – A state management library for React
The app in question had thousands of connected components, so that was a huge bottleneck for them. For many apps it doesn't matter.

The app that Recoil was originally extracted from has an extremely complex set of state and interdependent derived processes -- also heavily hooked into and modified by third-party plugins. This type of complexity is exactly what Recoil was designed to handle.

Thanks for your kind words.

davidmccabe··on Recoil – A state management library for React
Well, I know that on one tool we saw a 20x or so speedup compared to using Redux. This is because Redux is O(n) in that it has to ask each connected component whether it needs to re-render, whereas we can be O(1).

useReducer is equivalent to useState in that it works on a particular component and all of its descendants, rather than being orthogonal to the React tree.

I think if you can model something with pure functions, you should. That's the approach we try to take for asynchronous processes: just a pure function that you happen to evaluate on some other process. This obviates the need for things like sagas. So I agree with you there I guess.

If you post an example of what you don't think it could handle I will tell you how we would handle it.