Introduce createState which can be used in components to propagate updates

Summary:
Introduced a minimal state abstraction so that state can be maintained in the plugin instance, but subscribe to by the UI.

At a later point we could pick an off the shelve solution like Recoil or MobX, or introduce cursors to read something deep etc etc, but for now that doesn't seem to be needed at all, and I think this will be pretty comprehensible for plugin authors (see also the 25th diff in this stack).

The api

```
createState(initialValue): Atom

Atom {
   get() // returns current value
   set(newValue) // sets a new value
   update(draft => { }) // updates a complex value using Immer behind the scenes
}

// hook, subscribes to the updates of the Atom and always returns the current value
useValue(atom)
```

Reviewed By: nikoant

Differential Revision: D22306673

fbshipit-source-id: c49f5af85ae9929187e4d8a051311a07c1b88eb5
This commit is contained in:
Michel Weststrate
2020-07-01 08:58:40 -07:00
committed by Facebook GitHub Bot
parent 159c0deaf1
commit d16c6061c1
7 changed files with 117 additions and 10 deletions

View File

@@ -47,7 +47,7 @@ test('it can start a plugin and lifecycle events', () => {
});
test('it can render a plugin', () => {
const {renderer} = TestUtils.renderPlugin(testPlugin);
const {renderer, sendEvent, instance} = TestUtils.renderPlugin(testPlugin);
expect(renderer.baseElement).toMatchInlineSnapshot(`
<body>
@@ -59,7 +59,25 @@ test('it can render a plugin', () => {
</div>
</body>
`);
// TODO: test sending updates T68683442
sendEvent('inc', {delta: 3});
expect(renderer.baseElement).toMatchInlineSnapshot(`
<body>
<div>
<h1>
Hi from test plugin
3
</h1>
</div>
</body>
`);
// @ts-ignore
expect(instance.state.listeners.length).toBe(1);
renderer.unmount();
// @ts-ignore
expect(instance.state.listeners.length).toBe(0);
});
test('a plugin can send messages', async () => {
@@ -97,8 +115,8 @@ test('a plugin cannot send messages after being disconnected', async () => {
test('a plugin can receive messages', async () => {
const {instance, sendEvent} = TestUtils.startPlugin(testPlugin);
expect(instance.state.count).toBe(0);
expect(instance.state.get().count).toBe(0);
sendEvent('inc', {delta: 2});
expect(instance.state.count).toBe(2);
expect(instance.state.get().count).toBe(2);
});