From 7d8592a7f17c25e7977d2070deca50441e30006c Mon Sep 17 00:00:00 2001 From: "Daniel J. Lauk" Date: Wed, 7 Oct 2020 23:20:31 +0200 Subject: [PATCH 1/4] remove connect API from top level exports --- src/index.ts | 1 - typings/index.d.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index b964e0a..8d8a45f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ export * from './combineReducers' -export * from './connect' export * from './const' export * from './createModel' export * from './createStore' diff --git a/typings/index.d.ts b/typings/index.d.ts index 158be11..946f6cf 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,5 +1,4 @@ export * from './combineReducers' -export * from './connect' export * from './devtools' export * from './model' export * from './models' From 403acdf6b75efc6c3824942d818b3ef5b526a6db Mon Sep 17 00:00:00 2001 From: "Daniel J. Lauk" Date: Wed, 7 Oct 2020 23:20:11 +0200 Subject: [PATCH 2/4] rename connect.ts to components.ts --- rollup.config.js | 2 +- src/{connect.ts => components.ts} | 2 +- test/types/{connect.ts => components.ts} | 2 +- typings/{connect.d.ts => components.d.ts} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/{connect.ts => components.ts} (99%) rename test/types/{connect.ts => components.ts} (79%) rename typings/{connect.d.ts => components.d.ts} (100%) diff --git a/rollup.config.js b/rollup.config.js index f328ff0..d6ca0e1 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,10 +9,10 @@ export default { index: 'src/index.ts', combineReducers: 'src/combineReducers.ts', compat: 'src/compat.ts', + components: 'src/components.ts', const: 'src/const.ts', createModel: 'src/createModel.ts', createStore: 'src/createStore.ts', - connect: 'src/connect.ts', devtools: 'src/devtools.ts', persist: 'src/persist.ts', routing: 'src/routingPlugin.ts', diff --git a/src/connect.ts b/src/components.ts similarity index 99% rename from src/connect.ts rename to src/components.ts index 1e597a9..9d5e994 100644 --- a/src/connect.ts +++ b/src/components.ts @@ -1,5 +1,5 @@ import { Store } from '../typings/store' -import { Constructor, Connectable, DispatchMap } from '../typings/connect' +import { Constructor, Connectable, DispatchMap } from '../typings/components' import { stateEvent } from './const' const dispatchMap: unique symbol = Symbol() diff --git a/test/types/connect.ts b/test/types/components.ts similarity index 79% rename from test/types/connect.ts rename to test/types/components.ts index c0a7b57..3af6bbc 100644 --- a/test/types/connect.ts +++ b/test/types/components.ts @@ -1,6 +1,6 @@ import { assert, IsExact } from "conditional-type-checks" -import { DispatchMap } from '../../typings/connect' +import { DispatchMap } from '../../typings/components' const map: DispatchMap = { 'click': (_e: Event) => {}, diff --git a/typings/connect.d.ts b/typings/components.d.ts similarity index 100% rename from typings/connect.d.ts rename to typings/components.d.ts From 27e0fbfd0d23a50645972f254bb88aaa0538c78d Mon Sep 17 00:00:00 2001 From: "Daniel J. Lauk" Date: Wed, 7 Oct 2020 23:20:57 +0200 Subject: [PATCH 3/4] add connect API for svelte --- package.json | 3 +++ rollup.config.js | 1 + src/svelte.ts | 17 +++++++++++++++++ typings/svelte.d.ts | 6 ++++++ 4 files changed, 27 insertions(+) create mode 100644 src/svelte.ts create mode 100644 typings/svelte.d.ts diff --git a/package.json b/package.json index 69072fd..f8443ef 100644 --- a/package.json +++ b/package.json @@ -59,5 +59,8 @@ }, "dependencies": { "@captaincodeman/router": "^1.0.1" + }, + "peerDependencies": { + "svelte": "^3.0.0" } } diff --git a/rollup.config.js b/rollup.config.js index d6ca0e1..b372c9b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -17,6 +17,7 @@ export default { persist: 'src/persist.ts', routing: 'src/routingPlugin.ts', store: 'src/store.ts', + svelte: 'src/svelte.ts', thunk: 'src/thunk.ts', }, output: { diff --git a/src/svelte.ts b/src/svelte.ts new file mode 100644 index 0000000..35c682b --- /dev/null +++ b/src/svelte.ts @@ -0,0 +1,17 @@ +import { readable } from 'svelte/store' +import type { Store } from '../typings' + +export function connect(store: Store) { + const state = readable(store.state, (set) => { + const handler = () => { + set(store.state) + } + store.addEventListener('state', handler) + return () => store.removeEventListener('state', handler) + }) + + return { + subscribe: state.subscribe, + dispatch: store.dispatch, + } +} diff --git a/typings/svelte.d.ts b/typings/svelte.d.ts new file mode 100644 index 0000000..fb8c386 --- /dev/null +++ b/typings/svelte.d.ts @@ -0,0 +1,6 @@ +import type { Dispatch, Store } from './store' + +export declare function connect(store: Store): { + subscribe: (run: (value: S) => void, invalidate?: (value?: S) => void) => () => void + dispatch: Dispatch +} From fc4efa68ba41d6953a7bae9c9ea2c4264cc06d1d Mon Sep 17 00:00:00 2001 From: "Daniel J. Lauk" Date: Thu, 8 Oct 2020 00:31:22 +0200 Subject: [PATCH 4/4] docs: changes to connect API --- docs/api-connect.md | 45 ++++++++++++++++++++++++++++++++++++++++----- readme.md | 2 +- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/docs/api-connect.md b/docs/api-connect.md index c4c30ac..ffe6941 100644 --- a/docs/api-connect.md +++ b/docs/api-connect.md @@ -1,22 +1,30 @@ # connect -`connect` is a mixin that "connects" a web component to the store. It provides two methods: +The idiomatic expression for binding a component to a state store is to _connect_ it. Rdx's connect API comes in two flavours: One [for class based components](/api-connect?id=for-class-based-components-web-components) (e.g. web components), and one [for Svelte components](/api-connect?id=for-svelte-components). -## mapState +## For class based components (web components) + +```ts +import { connect } from '@captaincodeman/rdx/components' +``` + +The `connect` mixin creates a new base class for your web component. It provides two methods: + +### mapState `mapState(state: State)` passes the current store state to the component to allow it to extract the state it needs. It should return an object who's properties will be applied to the instance. It's good practice to use a package such as [reselect](https://github.com/reduxjs/reselect) to avoid unnecessary updates and also act as a buffer to insulate components from changes to the store state. -## mapEvents +### mapEvents `mapEvents()` defines a mapping from events that the component will listen to, and actions that it can dispatch to the store. The method should return an object that maps the event names to listen to, to the functions that will be called (usually to dispatch an action to the store using details from the event). -## Example +### Example for web components This example shows a simple counter component using [lit-element](https://lit-element.polymer-project.org/) connected to the store to display the current counter state and automatically dispatch actions to increment or decrement it. Not shown: the custom buttons would raise the `increment-counter` and `decrement-counter` custom events, or regular `@click` [lit-html event handlers](https://lit-html.polymer-project.org/) could be used to dispatch actions directly. ```ts import { LitElement } from 'lit-element' -import { connect } from '@captaincodeman/rdx' +import { connect } from '@captaincodeman/rdx/components' import { store, State } from './store' export class CounterElement extends connect(store, LitElement) { @@ -45,3 +53,30 @@ export class CounterElement extends connect(store, LitElement) { } } ``` + +## For Svelte components + +```ts +import { connect } from '@captaincodeman/rdx/svelte' +``` + +`connect` provides a [custom Svelte store](https://svelte.dev/tutorial/custom-stores) that your Svelte component can use to access the state in the store. + + +### Example for Svelte + +This example shows a simple counter component in [Svelte](https://svelte.dev), connected to the store to display the current counter state (which is just the count) and dispatch actions to increment or decrement it. + +```svelte + + + +{count} + +``` \ No newline at end of file diff --git a/readme.md b/readme.md index d206a5b..461fe3a 100644 --- a/readme.md +++ b/readme.md @@ -34,7 +34,7 @@ While the aim isn't to be 100% compatible with Redux, it can work with the Redux To create your state store: ```ts -import { Store, combineReducers, connect, thunk, persist, devtools} from '@captaincodeman/rdx' +import { Store, combineReducers, thunk, persist, devtools} from '@captaincodeman/rdx' // a very simple reducer state const counter = (state = 0, action) => {