Styleguide ideas
See original GitHub issueI thought I would share some styleguide ideas that are based on code we’ve been discussing before:
counter.ts: In the reducers there is a bug in TypeScript that does not check the object properties correctly when using the spread operator: https://github.com/Microsoft/TypeScript/issues/13878 . It will be fixed in TypeScript 2.4. After that the reducers will be type-safe.
import { Store, Reducer, Action } from "reactive-state";
export interface CounterState {
value: number;
}
export const initialCounterState = {
value: 0
}
export const increment = new Action<number>();
export const incrementReducer: Reducer<CounterState, number> = (state, payload = 1) => {
return { ...state, value: state.value + payload };
}
export const decrement = new Action<number>();
export const decrementReducer: Reducer<CounterState, number> = (state, payload = 1) => {
return { ...state, value: state.value - payload };
}
export const registerCounterReducers = (store: Store<CounterState>) => {
store.addReducer(increment, incrementReducer);
store.addReducer(decrement, decrementReducer);
// This part I'm not super happy about, more about it later in this post.
return {
increment,
decrement
}
}
export const registerCounterSelectors = (store: Store<CounterState>) => {
return {
getValue: store.select(s => s.value)
}
}
store.ts:
Function names could be thought about to not be too long, also they could maybe always start with the reducer name e.g. counterRegisterReducer
and counterInitialState
. This would make store.ts a bit cleaner and easier to read I guess.
import { Store, Reducer, Action } from 'reactive-state';
import { Observable } from 'rxjs/Observable';
import {
CounterState,
initialCounterState,
registerCounterReducers,
registerCounterSelectors
} from './reducers/counter';
export interface AppState {
counter: CounterState;
}
const appInitialState = {
counter: initialCounterState
}
export const rootState = Store.create(appInitialState);
const counterStore: Store<CounterState> = rootState.createSlice('counter');
export const counterActions = registerCounterReducers(counterStore);
export const counterSelectors = registerCounterSelectors(counterStore);
app.ts or anywhere you would like to use the store:
Always import Actions and Selectors from the same place. One thing that could make it easier and cleaner would be to make addReducer
return the action instead of the Subscription (maybe I use it wrong?).
import { AppState, counterActions, counterSelectors } from './store';
import { Observable } from 'rxjs/Observable';
class AppComponent {
testObservable$: Observable<number>;
constructor() {
this.testObservable$ = counterSelectors.getValue;
}
nextnumber() {
counterActions.increment.next();
}
}
Ideas and comments are more than welcome!
Issue Analytics
- State:
- Created 6 years ago
- Comments:10 (6 by maintainers)
Well for real-life scenario I assume one would use React/Angular/Vue, and in this case the registering of the modules with custom reducers/actions are most likely triggered by the component lifecycle callbacks:
ngOnInit
/ngOnDestroy
hooks in a component in AngularcomponentWillMount
/componentWillUnmount
in ReactbeforeCreated
/destroyed
hooks in VueIn React/Angular you would have “dumb” container components for your modules, which would be the perfect place to put the reducer registration/deregistation logic. I don’t know about Vue.js. Those dumb components would be created possible on a route, but also might be created upon user interaction etc.
FYI, in the meantime I have
react-redux
like bridge that mimics theconnect()
function fromreact-redux
, but is suited toreactive-state
to connect a store to a component. Currently it lives inreactive-state/dist/react
but will after some testing and feedback eventually moved to its own project (just likereact-redux
).reactive-state
as well as the react bridge described above. This could also serve as a starting point for a styleguide. The sample app uses react, react-router v4 and reactive-state.Let me know what you think.