Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Dispatch reducers

License

NotificationsYou must be signed in to change notification settings

jaystack/repatch

Repository files navigation

Repatch

npm versionnpm downloadscorp-check status

Dispatch reducers

Repatch is just a simplifiedRedux, that let you create actions more briefly by dispatching reducers directly.

draft

store.dispatch(state=>({ ...state,counter:state.counter+1}));

In this terminology, an action is a function that returns a reducer:

constincrement=amount=>state=>({  ...state,counter:state.counter+amount});store.dispatch(increment(42));

Motivation

Redux has verbose action management. The most of redux projects do not need sctrict action administration. Action types, action creators and the reducer's action handlers are mutually assigned to each other. Repatch's purpose is creating actions briefly.

The simplest way to keep the immutable action controlled dataflow and define actions briefly is dispatching pure functions (as reducers) to the store.

Comparison withRedux

Repatch is

  • less verbose
  • smaller (the minified version isless than 1 KB)
  • faster

than Redux.

Working withRedux

If you have to keep the official Redux in your project, then you can use theredux-repatch orredux-repatch-creator enhancers.

Examples

Articles

Repatch - the simplified Redux

Installation

npm install --save repatch

How to use

ES6

importStorefrom'repatch';conststore=newStore(initialState);

CommonJS

constStore=require('repatch').Store;

UMD

<scriptsrc="https://unpkg.com/repatch/dist/repatch.js"></script>

or the minified bundle:

<scriptsrc="https://unpkg.com/repatch/dist/repatch.min.js"></script>

and

constStore=Repatch.Store;constthunk=Repatch.thunk;

Compatibility withreact-redux

Repatch's interface is very similar to Redux, therefore you can use withreact-redux.

constunsubscribe=store.subscribe(()=>console.log(store.getState()));store.dispatch(resolveFetchingUsers(users));unsubscribe();

TODO app in brief

conststore=newStore([]);constaddTodo=text=>todos=>[...todos,{ text,checked:false}];constcheckTodo=index=>todos=>todos.map((todo,i)=>(i===index ?{ ...todo,checked:!todo.checked} :todo));consteditTodo=(index,text)=>todos=>todos.map((todo,i)=>(i===index ?{ ...todo, text} :todo));constremoveTodo=index=>todos=>todos.filter((_,i)=>i!==index);

Sub-reducers

We do not need to reduce always the whole state of the store. Repatch also offers a way to combine sub-reducers, those describe a deeply nested property in the state. We just define a helper function that takes a nested reducer as argument, and returns a reducer that reduces the whole state:

constreduceFoo=fooReducer=>state=>({  ...state,bar:{    ...state.bar,foo:fooReducer(state.bar.foo)}});

Using that we can define easily an action, that sets anx property in thefoo object:

constsetX=x=>reduceFoo(state=>({ ...state, x}));

Middlewares

A repatch middleware takes thestore instance, anext function and the previousreducer. The middleware can provide a new reducer via thenext function.

Middleware:Store->Next->Reducer->any

Use theaddMiddleware method to chaining middlewares:

conststore=newStore(initialState).addMiddleware(mw1).addMiddleware(mw2,mw3);

Middleware example

This simple logger middleware logs the current- and the next state:

constlogger=store=>next=>reducer=>{conststate=store.getState()constnextState=reducer(state)console.log(state,nextState)returnnext(_=>nextState)}conststore=newStore(initialState).addMiddleware(logger)

Async actions

Thethunk middleware is useful for handling async actions similar toredux-thunk.

importStore,{thunk}from'repatch';conststore=newStore(initialState).addMiddleware(thunk);

In thunk async actions reducer returns a function (delegate):

constupdateUser=delta=>state=>async(dispatch,getState)=>{try{consteditedUserId=getState().editedUser;dispatch(toggleSpinner(true));awaitapi.updateUser(editedUserId,delta);awaitdispatch(fetchUsers());}catch(error){dispatch(state=>({ ...state,error:error.message}))}finally{dispatch(toggleSpinner(false));}};

It is possible to embed async actions within each other too and awaiting their resolving:

awaitdispatch(fetchUsers());

Injecting extra argument

It is possible to inject extra arguments into async actions:

importStore,{thunk}from'repatch';importapifrom'./api';import{hashHistory}from'react-router';conststore=newStore(initialState).addMiddleware(thunk.withExtraArgument({ api, hashHistory}));

Then you can access these arguments in your delegates:

constupdateUser=delta=>state=>async(dispatch,getState,{ api, hashHistory})=>{// ...}

This way you can keep your async actions independently from outer instances or side-effects. This practice is useful for testing.

Testing

Sync actions

Testing a reducer is easy:

import*asassertfrom'assert';import{changeName}from'./actions';// ...it('changeName',()=>{conststate={name:'john'};constnextState=changeName('jack')(state);assert.strictEqual(nextState.name,'jack');});

Async actions

For async action tests you need to instantiate theStore and provide mocked extra arguments.

importStore,{thunk}from'repatch';import*asassertfrom'assert';import{fetchUsers}from'./actions';constmockUsers=[{username:'john'}];constmockApi={getUsers:()=>Promise.resolve(mockUsers)}// ...it('fetchUsers',async()=>{conststate={users:[]};conststore=newStore(state).addMiddleware(thunk.withExtraArgument({api:mockApi}));awaitstore.dispatch(fetchUsers());constnextState=store.getState();assert.deepEqual(nextState.users,mockUsers);});

License

MIT

Community

https://twitter.com/repatchjs

Developed by

JayStack


[8]ページ先頭

©2009-2025 Movatter.jp