bitovi / ylem

Add Observable View-Models to React components
https://bitovi.github.io/ylem/
MIT License
42 stars 2 forks source link

Support Hooks [WIP] #192

Closed christopherjbaker closed 1 year ago

christopherjbaker commented 5 years ago

This is an attempt at #191. The old code is still in place, though it has been moved to the legacy folder.

Usage

useStore

The primary use. Pass a Store constructor and props, returns and observable to use in the render.

function TestComponent(props) {
  const { foo, bar } = useStore(Store, props);

  return <div>{foo}{bar}</div>;
}

useObserver

An alternative use when you have an existing store and just need observability.

function TestComponent() {
  useObserver();

  return <div>{store.foo}{store.bar}</div>;
}

ModelProvider

Though the idea is not hook-specific, we have been discussing this for quite some time, so I decided to include it in the PR. Allows you to provide model classes at higher levels and consume them lower. Searches cascade up the tree.

Obviously this is a contrived example, to show multiple definitions in a single provider, as well as nested providers.

function TestComponent(props) {
  const Foo = useModel('Foo');
  const Bar = useModel('Bar');
  const Bam = useModel('Bam');

  const foo = useStore(Foo, props);
  const bar = useStore(Bar, props);
  const bam = useStore(Bam, props);

  return <div data-testid="foo">{foo.name} {bar.name} {bam.name}</div>;
}

function TestComponent(props) {
  return (
    <ModelProvider Foo={Foo}>
      <ModelProvider Bar={Bar} Bam={Bam}>
        <TestComponent />
      </ModelProvider>
    </ModelProvider>
  );
}
BigAB commented 5 years ago

@christopherjbaker after reading https://overreacted.io/why-isnt-x-a-hook/ I am not sure our API choice is optimal.

Namely, the timing of when you call the useStore() matters, because it sets up listeners, so read before it aren't registered and opening a new observer closes the last one, which may break composition.

What are your thoughts?

christopherjbaker commented 5 years ago

TLDR: We are providing something that sits outside the norm of React, but I don't think we violate anything brought up in that article.

@BigAB That was a good read. I don't think we violate the issues brought up in that article though. useStore and useObserver do not break composition. I think it is perfectly reasonable that you cannot use observables until after you declare that you are going to, in the same way that you cannot use state until after you declare said state. You can absolutely useStore multiple times (this will create multiple observation readers under the hood, but that will not cause any issues), and debugging does not become any more complicated (other than what observables themselves add).