Skip to content

Instantly share code, notes, and snippets.

@bcherny
Last active June 11, 2018 00:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcherny/f360f417e8768558684ec3e379f9e354 to your computer and use it in GitHub Desktop.
Save bcherny/f360f417e8768558684ec3e379f9e354 to your computer and use it in GitHub Desktop.
Thoughtstream: GC'able Undux stores

Thoughtstream: GC'able Undux stores

  • Stores would no longer be singletons
  • No top level createStore
  • Instead, use store factory that creates store instances
  • Created for you as part of connect from an initial state
let withStore = connect({
  a: 1,
  b: 2
}, withEffects)

withStore(
  class extends React.Component {...}
)

withStore.markRoot(
  class extends React.Component {...}
)
  • 2 types of connected React Components: Owners and Consumers
  • When an Owner node (as indicated by markRoot) is unmounted, its store instance is dereferenced and GC'd
  • Problem: How do we know the store is no longer used by other nodes?
    • Solution: Refcount - increment on withStore call, decrement on unmount
  • Problem: What happens when root node is unmounted, but due to improper setup the store is still referenced by another component?
    • Solution: Is the best we can do a runtime error? Or can we catch this at compile time (eg. by enforcing that a consumer node cannot have an Owner as its child)? We can probably enforce 1 layer deep ({children: Not<Owner<State>>}), but it's hard to enforce >1 layer deep with static analysis.
  • RESOLUTION: We need a better way to statically enforce that the store root is the parent node of all store consumers, so that we can guarantee it'll be the last to unmount. Otherwise, if a user accidentally puts an Owner node within a Consumer node (ie. the Consumer is the Owner's parent in the React tree), then the Owner might unmount and dereference its store, but because the Consumer still references the store, we're in a weird state where the consumer is stuck with an indefinitely stale view of the world.
    • Solution: Context API - Provider creates store, Consumer uses it
      • TODO: What happens when a Consumer is a Provider's parent (used illegally). According to React docs that will prevent automatically re-rendering children, but will it still hold a reference to the store?
    • TODO: How does that work with React Portals?
_ rootA
  |_ consumerA
  |_ rootB
    |_ consumerB
    |_ consumerA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment