Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ionic-team/stencil-redux
https://github.com/ionic-team/stencil-redux
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/ionic-team/stencil-redux
- Owner: ionic-team
- License: mit
- Archived: true
- Created: 2017-07-21T15:29:29.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2022-06-24T17:31:25.000Z (over 2 years ago)
- Last Synced: 2024-05-23T03:43:42.941Z (7 months ago)
- Language: TypeScript
- Size: 1.13 MB
- Stars: 97
- Watchers: 20
- Forks: 20
- Open Issues: 28
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-stenciljs - Stencil Redux - A simple redux connector for Stencil-built web components inspired by react-redux. (List of Awesome Components Made using StencilJS / State Management)
README
## Stencil Redux
A simple redux connector for Stencil-built web components inspired by [`react-redux`](https://github.com/reduxjs/react-redux).
## Install
```
npm install @stencil/redux
npm install redux
```## Usage
Stencil Redux uses the [`redux`](https://github.com/reduxjs/redux/) library underneath. Setting up the store and defining actions, reducers, selectors, etc. should be familiar to you if you've used React with Redux.
### Configure the Root Reducer
```typescript
// redux/reducers.tsimport { combineReducers } from 'redux';
// Import feature reducers and state interfaces.
import { TodoState, todos } from './todos/reducers';// This interface represents app state by nesting feature states.
export interface RootState {
todos: TodoState;
}// Combine feature reducers into a single root reducer
export const rootReducer = combineReducers({
todos,
});
```### Configure the Actions
```typescript
// redux/actions.tsimport { RootState } from './reducers';
// Import feature action interfaces
import { TodoAction } from './todos/actions';// Export all feature actions for easier access.
export * from './todos/actions';// Combine feature action interfaces into a base type. Use union types to
// combine feature interfaces.
// https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types
export type Action = (
TodoAction
);
```### Configure the Store
```typescript
// redux/store.tsimport { Store, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk'; // add-on you may want
import logger from 'redux-logger'; // add-on you may wantimport { RootState, rootReducer } from './reducers';
export const store: Store = createStore(rootReducer, applyMiddleware(thunk, logger));
```### Configure Store in Root Component
```typescript
// components/my-app/my-app.tsx
import { store } from '@stencil/redux';
import { Action } from '../../redux/actions';
import { RootState } from '../../redux/reducers';
import { initialStore } from '../../redux/store';@Component({
tag: 'my-app',
styleUrl: 'my-app.scss'
})
export class MyApp {componentWillLoad() {
store.setStore(initialStore);
}}
```### Map state and dispatch to props
:memo: *Note*: Because the mapped props are technically changed *within* the component, `mutable: true` is required for `@Prop` definitions that utilize the store. See the [Stencil docs](https://stenciljs.com/docs/properties#prop-value-mutability) for info.
```typescript
// components/my-component/my-component.tsximport { store, Unsubscribe } from '@stencil/redux';
import { Action, changeName } from '../../redux/actions';
import { RootState } from '../../redux/reducers';@Component({
tag: 'my-component',
styleUrl: 'my-component.scss'
})
export class MyComponent {
@Prop({ mutable: true }) name: string;changeName!: typeof changeName;
unsubscribe!: Unsubscribe;
componentWillLoad() {
this.unsubscribe = store.mapStateToProps(this, state => {
const { user: { name } } = state;
return { name };
});store.mapDispatchToProps(this, { changeName });
}componentDidUnload() {
this.unsubscribe();
}doNameChange(newName: string) {
this.changeName(newName);
}
}
```### Usage with `redux-thunk`
Some Redux middleware, such as `redux-thunk`, alter the store's `dispatch()` function, resulting in type mismatches with mapped actions in your components.
To properly type mapped actions in your components (properties whose values are set by `store.mapDispatchToProps()`), you can use the following type:
```typescript
import { ThunkAction } from 'redux-thunk';export type Unthunk = T extends (...args: infer A) => ThunkAction
? (...args: A) => R
: T;
```#### Example
```typescript
// redux/user/actions.tsimport { ThunkAction } from 'redux-thunk';
export const changeName = (name: string): ThunkAction, RootState, void, Action> => async (dispatch, getState) => {
await fetch(...); // some async operation
};
```In the component below, the type of `this.changeName` is extracted from the action type to be `(name: string) => Promise`.
```typescript
// components/my-component/my-component.tsximport { changeName } from '../../redux/actions';
export class MyComponent {
changeName!: Unthunk;componentWillLoad() {
store.mapDispatchToProps(this, { changeName });
}
}
```