Relay: [meta] Make all state contextual

Created on 7 Nov 2015  Â·  19Comments  Â·  Source: facebook/relay

This is a meta-task to track progress toward making all Relay state contextual, such that multiple instances of Relay can be run in the same JS context. The primary motivation is to support server rendering in open source, where sharing JS contexts is the norm.

Tasks:

  • [x] GraphQLQueryRunner
  • [x] GraphQLPendingQueryTracker should write query results into the contextual RelayStoreData instance
  • [x] GraphQLDeferredQueryTracker: should read query root IDs from the contextual RelayStoreData instance
  • [x] RelayMutationTransaction should write mutation results into the contextual RelayStoreData instance
  • [x] GraphQLStoreRangeUtils - this holds a global mapping of dataID -> range information, and will have to be made contextual. The primary caller is readRelayQueryData.
  • [x] GraphQLStoreChangeEmitter notifies components (or other observers) of data when it changes.
  • [x] Create RelayEnvironment
  • [x] Make RelayStore a singleton instance of RelayEnvironment
  • [x] Change RelayContainer/RelayRenderer to access data via the React context
  • [x] Contextualize RelayRenderer
  • [x] Make Relay.injectTaskScheduler a method on RelayEnvironment
  • [x] Contextualize the network layer and Relay.injectNetworkLayer
  • [x] Contextualize Relay mutations (cannot create props until the store to which it will be applied is known) (#699)

Note: the following will be completed as part of #559:

  • [ ] Document RelayEnvironment, make it accessible via Relay.Environment or other, and remove any unsupported APIs (or mark them as such).
  • [ ] Promote RelayRenderer to public API
enhancement

Most helpful comment

Great news. Big thanks to all the contributors!

img

All 19 comments

cc @devknoll who's started experimenting with this in #557

Optionally, Relay.injectTaskScheduler and Relay.injectNetworkLayer could be moved to the Relay Context class to allow different schedulers/network layers per context.

I think this is actually fairly critical for server side rendering.

@josephsavona Do we want RelayStore to own the RelayStoreData instances? Seems like yes, but wanted to confirm.

@josephsavona Also GraphQLStoreRangeUtils seems a little tough. Not sure who should own the instance in this case. Going to try keeping it in RelayStoreData and passing it down.

The methods for injecting these should be on Relay.Store since that's public, but they should save the scheduler/network layer to RelayStoreData.

Re RangeUtils, agree this map can be saved into StoreData.

Looks like GraphQLStoreChangeEmitter depends on GraphQLStoreRangeUtils too. How should we approach that?

I was on my phone earlier, so here's more context on each of the above

GraphQLStoreChangeEmitter also needs to be contextualized. It doesn't need to depend on GraphQLStoreRangeUtils - instead, RelayStoreData could be changed to call changeEmitter.broadcastChangeForID with an ID that is already in canonical form. RelayStoreData will own the range utils so this should be okay.

Re the distinction between RelayStore and RelayStoreData - in the interim, it's probably best to put all public methods on RelayStore, while holding and modifying all state in RelayStoreData.

Super helpful, thanks :+1:

@josephsavona you can use this syntax to track subtasks:

* [ ] In progress
* [x] Done

Result:

  • [ ] In progress
  • [x] Done

is there a timeline for release? I'd love to contribute, but finding the time to get up to speed with the internals would probably be longer than it'd take you to finish.

Just a heads up that this and the react-relay/Relay core split will be my main area of focus for the next couple months. Contributions are welcome, but definitely reach out to us before starting a major PR in this area.

@leebensen there are always things that need attention. I'd recommend starting with a small task at first - take a look at issues tagged with "good first bug"!

Heads up that we're renaming RelayContext to RelayEnvironment. It's common in Relay apps to render multiple RelayRootContainers (e.g. one for each tab in a TabView), and RelayContext suggests an incorrect association with React contexts which are one-per-root component.

As of 8e53183bd4f323196a71f471d6275fe024706a66, all of Relay's internal state tracking has been contextualized. Each instance of RelayEnvironment is an isolated environment with its own cache of data, network layer, task scheduler, etc. This is an important prerequisite for server rendering in open source as well as allowing some new use cases. The next step is #559 - splitting Relay Core and the React/Relay integration layer - follow along there for more details.

Thanks especially to @denvned and @devknoll for their impressive contributions!

Awesome. Looking forward to it! :tada:

Amazing work! Thanks @denvned, @devknoll, @josephsavona . :tada:

Yeah!

On Wed, Mar 9, 2016 at 6:59 AM Rodrigo Ribeiro [email protected]
wrote:

Amazing work! Thanks @denvned https://github.com/denvned, @devknoll
https://github.com/devknoll, @josephsavona
https://github.com/josephsavona . [image: :tada:]

—
Reply to this email directly or view it on GitHub
https://github.com/facebook/relay/issues/558#issuecomment-194333793.

Great news. Big thanks to all the contributors!

img

Was this page helpful?
0 / 5 - 0 ratings