Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 40 additions & 5 deletions docs/api-connect.md
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down Expand Up @@ -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
<script lang="ts">
import { connect } from '@captaincodeman/rdx/svelte'
import { store, dispatch } from './store'

const state = connect(store)
$: count = $state.counter
</script>

<button on:click={() => {dispatch.counter.increment()}}> + </button>
<span>{count}</span>
<button on:click={() => {dispatch.counter.decrement()}}> - </button>
```
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,8 @@
},
"dependencies": {
"@captaincodeman/router": "^1.0.1"
},
"peerDependencies": {
"svelte": "^3.0.0"
}
}
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
3 changes: 2 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ 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',
store: 'src/store.ts',
svelte: 'src/svelte.ts',
thunk: 'src/thunk.ts',
},
output: {
Expand Down
2 changes: 1 addition & 1 deletion src/connect.ts → src/components.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand Down
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './combineReducers'
export * from './connect'
export * from './const'
export * from './createModel'
export * from './createStore'
Expand Down
17 changes: 17 additions & 0 deletions src/svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { readable } from 'svelte/store'
import type { Store } from '../typings'

export function connect<S>(store: Store<S>) {
const state = readable<S>(store.state, (set) => {
const handler = () => {
set(store.state)
}
store.addEventListener('state', handler)
return () => store.removeEventListener('state', handler)
})

return {
subscribe: state.subscribe,
dispatch: store.dispatch,
}
}
2 changes: 1 addition & 1 deletion test/types/connect.ts → test/types/components.ts
Original file line number Diff line number Diff line change
@@ -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) => {},
Expand Down
File renamed without changes.
1 change: 0 additions & 1 deletion typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './combineReducers'
export * from './connect'
export * from './devtools'
export * from './model'
export * from './models'
Expand Down
6 changes: 6 additions & 0 deletions typings/svelte.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Dispatch, Store } from './store'

export declare function connect<S>(store: Store<S>): {
subscribe: (run: (value: S) => void, invalidate?: (value?: S) => void) => () => void
dispatch: Dispatch
}