Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

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

Utils to define react redux reducers/actions in typescript.

NotificationsYou must be signed in to change notification settings

cimdalli/redux-ts

Repository files navigation

Utils to define react redux reducer/action in typescript.

build statusdependencies StatusdevDependencies Statusnpm version

Now FSA compliant

For breaking changes you can take lookCHANGELOG

Installation

# npmnpm install --save redux-ts# yarnyarn add redux-ts

Usage

Quickstart

This is all in one reference implementation ofredux-ts library. You can enhance that solution depend on your needs.

import{StoreBuilder,ReducerBuilder}from'redux-ts'// Define reducer statetypeLayoutState={isDark:boolean}// Define store statetypeStoreState={layout:LayoutState}// Define actionconstswitchTheme=createAction('switchTheme')// Build reducerconstlayoutReducer=newReducerBuilder<LayoutState>().handle(switchTheme,(state,action)=>{constisDark=!state.layout.isDarkreturn{ ...state, isDark}},)// Build storeexportconst{ mapStoreToProps, connected, ...store}=newStoreBuilder<StoreState>().withReducerBuildersMap({layout:layoutReducer}).withDevTools()// enable chrome devtools.build()
importReactfrom'react'import{mapDispatchToProps}from'redux-ts'import{connected,mapStoreToProps,store}from'./store'// Map store to component propsconststoreProps=mapStoreToProps(store=>({theme:store.layout.isDark ?'dark' :'light',}))// Pass action object to create dispatchable func. (aka. bindActionCreators)constdispatchProps=mapDispatchToProps({ switchTheme})// Connect componentconstConnectedMain=connected(storeProps,dispatchProps)(({ theme, switchTheme})=>(<div><span>Current theme:{theme}</span><buttononClick={switchTheme}>Switch theme</button></div>))// Connect storeconstRoot:React.FC=props=>(<Providerstore={store}><ConnectedMain/></Provider>)ReactDOM.render(<Root/>,document.getElementById('app'))

Use case (connected-react-router)

This is sample usage ofconnected-react-router withredux-ts

import{StoreBuilder}from'redux-ts'import{createBrowserHistory}from'history'import{connectRouter,routerMiddleware}from'connected-react-router'exportconsthistory=createBrowserHistory()constrouterReducer=connectRouter(history)exportconststore=newStoreBuilder<StoreState>().withMiddleware(routerMiddleware(history)).withReducer('router',routerReducer).withDevTools()// enable chrome devtools.build()
import{Provider}from'react-redux'import{Route,Switch}from'react-router'import{ConnectedRouter}from'connected-react-router'import{history,store}from'./store'ReactDOM.render(<Providerstore={store}><ConnectedRouterhistory={history}><Switch><Routeexactpath="/"render={()=><div>Match</div>}/><Routerender={()=><div>Miss</div>}/></Switch></ConnectedRouter></Provider>,document.getElementById('react-root'),)

Using react-ts

Store

Create redux store with builder pattern.

import{StoreBuilder}from'redux-ts'import{authReducer}from'./reducers/authReducer'exportconst{ connected, mapStoreToProps, ...store}=newStoreBuilder<StoreState>().withInitialState({test:true}).withMiddleware().withReducer("auth",authReducer).withDevTools().build();}
  • As generic parameter, it requires store state type in order to match given reducers and the state.
  • Any number of middleware, enhancer or reducer can be used to build the state.
  • mapStoreToProps is a dummy method that returns passed parameter again. This method can be used to map store object to props which are consumed from connected components. Return type isMapStateToPropsParam which is compatible withconnect.
  • connected function is also another dummy function that wraps originalconnect function but with implicit type resolution support. Problem with original one, when you connect your component with connect method, it is trying to resolve typing by matching signature you passed as parameters to connect(mapStateToProps, mapDispatchToProps) and component own properties. If you are using explicit typing mostly, it is totally fine to use original one. But if you are expecting implicit type resolution, original connect is failing and resolving inner component type asnever.

Actions

Action declaration can be done withcreateAction function which takes action name as parameter and payload type as generic type.Each action should have unique identifier which is first parameter ofcreateAction function. You can also define your metadata type and pass to generic type as second argument.

import{createAction}from'redux-ts'typeLoginPayload={username:string;password:string}typeSetTokenPayload={token?:string}typeTokenMeta={createdAt:Date}exportconstLogin=createAction<LoginPayload>('Login')exportconstLogout=createAction('Logout')exportconstSetToken=createAction<SetTokenPayload,TokenMeta>('SetToken')

Reducers

Reducers are consumer functions that consumes actions and change application state. Difference from original redux implementation inredux-ts, reducers can also dispatch another action asynchronously. Each reducer method should return state value even it doesn't change it. Async dispatch operations will be handled after original dispatch cycle is finished.

import{ReducerBuilder}from'redux-ts'import{Login,Logout,SetToken}from'../actions'import{push}from'connected-react-router'consttokenKey='auth'typeAuthState={token?:string}exportconstauthReducer=newReducerBuilder<AuthState>()// Initial value of sub state.init({token:localStorage.getItem(tokenKey)||undefined,})// Handle SetToken action.handle(SetToken,(state,action)=>{const{ token}=action.payloadif(token){// If token is valid, persist it on local storagelocalStorage.setItem(tokenKey,token)}else{// Otherwise remove from local storagelocalStorage.removeItem(tokenKey)}return{ ...state, token}})// Handle Logout action.handle(Logout,(state,action,dispatch)=>{dispatch(SetToken({token:undefined}))// First clear tokendispatch(push('/dashboard'))// Then navigate to home page, it should redirect to login pagereturnstate// Return state even there is no change})// Handle Login action.handle(Login,(state,action,dispatch)=>{const{ username, password}=action.payload// Request to loginfetch(`https://server.com/login?u=${username}&p=${password}`).then(x=>x.json()).then(data=>{// If valid, store token and navigate to home pagedispatch(SetToken(data.token))dispatch(push('/dashboard'))})returnstate})

Connect

connect method is part ofreact-redux library that allows you to connect your react components with redux store.

You can useconnected method for implicit type resolution.

import*asReactfrom'react'import{mapDispatchToProps}from'redux-ts'import{store}from'../store'import{ChangeTheme}from'../actions/layout.actions'import{Logout}from'../actions/auth.actions'const{ mapStoreToProps, connected}=store// Map store object to component propsconststoreProps=mapStoreToProps(store=>({useDarkTheme:!!store.layout.useDarkTheme}))// Map actions to component propsconstdispatchProps=mapDispatchToProps({  Logout,  ChangeTheme})exportconstLayout=connected(storeProps,dispatchProps)(({  children,// standard react prop  useDarkTheme,// mapped store prop  Logout,// mapped action prop  ChangeTheme// mapped action prop})=>{constappBarRightElement=(<div><ToggleonToggle={ChangeTheme}label={useDarkTheme:'dark' :'light'}toggled={useDarkTheme}/><FlatButtononClick={Logout}label="logout"/></div>)return(<div><AppBariconElementRight={appBarRightElement}/>{children}</div>)})

Example

react-material-demo (Not up to date)

License

MIT


[8]ページ先頭

©2009-2025 Movatter.jp