diff --git a/README.md b/README.md index c239bca..f69f76c 100644 --- a/README.md +++ b/README.md @@ -71,11 +71,34 @@ When you call `updateState`, your new data will be merged with the current data
+

+ +

+ +The other side of the coin is the UsePlug Hook. This way you can Plug your component into your newly created Store and at each change, the store data update your component's state. + +```javascript +const TestComponent = (props) => { + const { name } = props; + const state = usePlug(state$) + return ( +
+

{name}

+

Total: {total}

+

The store was{changed ? '' : `n't`} changed.

+
+ ) +} +``` + +
+

-The other side of the coin is the Plug HOC. This way you can Plug your component into your newly created Store and at each change, the store data will be forwarded as props to your component. +**Use Luffie like this if your React doesn't support Hooks** +If you use a older version of React without Hooks, you can use the Plug HOC to connect your component with you store state following the steps described below: **1. Create your Container** diff --git a/__tests__/use-stream.spec.tsx b/__tests__/use-stream.spec.tsx new file mode 100644 index 0000000..716919c --- /dev/null +++ b/__tests__/use-stream.spec.tsx @@ -0,0 +1,40 @@ +import * as React from 'react'; +import { render, cleanup, waitForElement } from 'react-testing-library'; +import 'jest-dom/extend-expect' +import { setTotal10ChangedTrue, cleanStore } from '../lib/utils/example-store'; +import { UsePlugTestComponent } from '../lib/utils/example-usestream'; + +describe('Plug', () => { + afterEach(cleanup); + afterAll(() => cleanStore()) + + it('Renders', async done => { + const { getByTestId } = render(); + + const nameNode = await waitForElement(() => getByTestId('name')) + const totalNode = await waitForElement(() => getByTestId('total')) + const changedNode = await waitForElement(() => getByTestId('changed')) + + expect(nameNode).toHaveTextContent('Test Testersson'); + expect(totalNode).toHaveTextContent('Total: 0'); + expect(changedNode).toHaveTextContent(`The store wasn't changed`); + done(); + }) + + it('Renders with new State', async done => { + setTotal10ChangedTrue(); + + const { getByTestId } = render(); + + const nameNode = await waitForElement(() => getByTestId('name')) + const totalNode = await waitForElement(() => getByTestId('total')) + const changedNode = await waitForElement(() => getByTestId('changed')) + + expect(nameNode).toHaveTextContent('Test Testersson'); + expect(totalNode).toHaveTextContent('Total: 10'); + expect(changedNode).toHaveTextContent(`The store was changed`); + done(); + }) +}) + + diff --git a/assets/luffiejs-usestream.png b/assets/luffiejs-usestream.png new file mode 100644 index 0000000..4bc7ae7 Binary files /dev/null and b/assets/luffiejs-usestream.png differ diff --git a/lib/index.ts b/lib/index.ts index e14cfd5..94b23f3 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,9 @@ import { plug } from "./plug"; import { createStore } from "./store"; +import { useStream } from "./use-stream"; export { plug, - createStore + createStore, + useStream, } \ No newline at end of file diff --git a/lib/use-stream.ts b/lib/use-stream.ts new file mode 100644 index 0000000..89a95bf --- /dev/null +++ b/lib/use-stream.ts @@ -0,0 +1,16 @@ +import { useState, useEffect } from "react"; +import { Observable } from "rxjs"; + +export function useStream(stream: Observable) { + const [streamData, setStreamData] = useState(null); + + useEffect(() => { + const sub = stream.subscribe(data => setStreamData(data)); + + return () => { + sub.unsubscribe(); + } + }) + + return streamData; +} \ No newline at end of file diff --git a/lib/utils/example-store.ts b/lib/utils/example-store.ts index c88e0a4..d5c4134 100644 --- a/lib/utils/example-store.ts +++ b/lib/utils/example-store.ts @@ -24,10 +24,15 @@ const setTotalDouble = () => updateState((state: any) => ({ total: state.total * 2 })); +const cleanStore = () => { + updateState(initialState); +} + export { state$, getCurrentState, setTotal10ChangedTrue, setTotal20, - setTotalDouble + setTotalDouble, + cleanStore } \ No newline at end of file diff --git a/lib/utils/example-usestream.tsx b/lib/utils/example-usestream.tsx new file mode 100644 index 0000000..6878305 --- /dev/null +++ b/lib/utils/example-usestream.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; + +import { useStream } from '../use-stream'; +import { state$ } from './example-store'; + +interface IProp { + name: string; +} + +const UsePlugTestComponent = (props: IProp) => { + const state = useStream(state$); + if(!state) return null; + + return ( +
+

{props.name}

+

Total: {state.total}

+

The store was{state.changed ? '' : `n't`} changed.

+
+ ) +} + +export { + UsePlugTestComponent, +} \ No newline at end of file