Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

State management prototype #2027

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

State management prototype #2027

wants to merge 1 commit into from

Conversation

smashwilson
Copy link
Contributor

I've been musing about #1437 recently. This is a prototype for a possible context-based state management framework we could use to address our prop-drilling woes.

My specific goals for this are:

  • Avoid contributing to "wrapper hell" or requiring nested higher-order components. These make it challenging to read the React dev tools or Enzyme's .debug() output.
  • Producer and consumer components should both be easily testable by Enzyme using the shallow renderer.
  • Subscribing to a collection of asynchronous properties should be a first-class concept. One of the primary use-cases of this is to consume the "current" Repository.
  • Consider that properties may be expensive to fetch. Property values (synchronous or asynchronous) should only be evaluated when a child component that is currently rendered will actually consume them.
  • The smallest subtrees that actually require a re-render on a property change should be re-rendered.
  • Avoid unnecessary re-renders.

API

Here's a draft of the initial API that I've come up with:

import React from 'react';

import Courier from '../courier';

export default class SomeView extends React.Component {
  static mailbox = {
    atom: ['tooltips', 'config'],
    repo: ['workingDirectory', 'remotes', 'branches'],
    login: ['token'],
  };

  render() {
    // true if *any* of the async properties are still being fetched
    if (this.m.isLoading()) {
      return <LoadingView />;
    }

    // Synchronous and asynchronous property values alike are available on `this.m`.
    return (
      <div>
        <p>{this.m.repo.workingDirectory}</p>
        <p>{this.m.repo.remotes.getHeadBranch().getName()</p>
      </div>
    );
  }
}

Courier.register(SomeView);

And on the provider side:

import React from 'react';

import Courier from '../courier';

export default class SomeContainer {
  render() {
    return (
      <Courier.Provider
        registerProviders={this.registerProviders}
        atom={this.props.atomEnv}
        repo={this.props.repository}>
        <SomeChild />
      </Courier.Provider>
    );
  }

  registerProviders = courier => {
    courier.provider('atom', c => {
      c.syncProperty('tooltips', model => model.tooltips);
      c.syncProperty('config', model => model.config);
    });

    courier.provider('repo', c => {
      // Subscribe to "onDidUpdate" and re-evaluate properties when it fires
      c.observeModel();
      c.syncProperty('workingDirectory', model => model.getWorkingDirectoryPath());
      c.asyncProperty('remotes', model => model.getRemotes());
      c.asyncProperty('branches', model => model.getBranches());
    });
  }
}

Remaining

  • Subscribe to model updates with c.observeModel().
  • Test coverage for the Courier to ensure we're working properly and rendering when we expect to render.
  • Figure out how to allow nested providers.
  • Come up with a better name if we don't like the post office / mailbox / courier metaphor.

External factors

@codecov
Copy link

codecov bot commented Mar 25, 2019

Codecov Report

Merging #2027 into master will decrease coverage by 0.11%.
The diff coverage is 81.96%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2027      +/-   ##
==========================================
- Coverage   92.58%   92.46%   -0.12%     
==========================================
  Files         189      190       +1     
  Lines       11244    11366     +122     
  Branches     1634     1650      +16     
==========================================
+ Hits        10410    10510     +100     
- Misses        834      856      +22
Impacted Files Coverage 螖
lib/courier.js 81.96% <81.96%> (酶)

Continue to review full report at Codecov.

Legend - Click here to learn more
螖 = absolute <relative> (impact), 酶 = not affected, ? = missing data
Powered by Codecov. Last update a7082db...7ce8796. Read the comment docs.

@smashwilson smashwilson mentioned this pull request Apr 5, 2019
46 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant