react-reducer-provider v5.1.0
react-reducer-provider provides a centralized state, managed asynchronously or synchronously through a reducer, mapper or actuator.
Quick Start
1 . Add dependency:
package.json:
when using hooks:
..
"dependencies": {
"react": ">=16.8.0"
"react-reducer-provider": "5.1.0",
..when using HOC:
..
"dependencies": {
"react": ">=16.0.0"
"react-reducer-provider": "5.1.0",
..Reducers
2 . Create the AsyncReducerProvider or SyncReducerProvider component to manage the centralized state:
a . Define the initial state.
b . Define the reducer function.
c . Define the Reducer Provider.
SomeReducerProvider.jsx:
import React from 'react'
import { SyncReducerProvider } from 'react-reducer-provider'
const initialState = 0
function reduce(prevState, action, delta) {
switch (action) {
case 'ACTION1':
return prevState + delta
case 'ACTION2':
return prevState - delta
default:
return prevState
}
}
function SomeReducerProvider({ children }) {
return (
<SyncReducerProvider
reducer={reduce}
initialState={initialState}
>
{children}
</SyncReducerProvider>
)
}
export default SomeReducerProvider3 . Access the state and the dispatcher of the Provider component using the hooks or HOC provided by 'react-reducer-provider':
useReducer/injectReducer.useReducerDispatcher/injectReducerDispatcher.useReducerState/injectReducerState.
SomeComponent1.jsx => using useReducer:
import { useReducer } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponent1() {
const { state, dispatch } = useReducer()
return (
<button onClick={() => dispatch('ACTION1', 2)}>
Go up (from {state})!
</button>
)
}SomeComponent2.jsx => using injectReducerDispatcher:
import { injectReducerDispatcher } from "react-reducer-provider";
import React from "react";
class SomeComponent2 extends React.Component {
render() {
return (
<button onClick={() => {
const newState = dispatch('ACTION2', 1)
console.info(newState)
}}>
Go down!
</button>
)
}
}
export default injectReducerDispatcher(SomeComponent2, 'dispatch')SomeComponentN.jsx => using useReducerState:
import { useReducerState } from 'react-reducer-provider'
import React from 'react'
export default function SomeComponentN() {
const currentState = useReducerState()
return (
<div>
Current:{currentState}
</div>
)
}4 . Wrap components which will consume the SomeReducerProvider component:
SomeContainer.jsx:
import SomeComponent1 from './path/to/SomeComponent1'
import SomeComponent2 from './path/to/SomeComponent2'
import SomeComponentN from './path/to/SomeComponentN'
import SomeReducerProvider from '../path/to/SomeReducerProvider'
import React from 'react'
export default function SomeContainer() {
return (
<SomeReducerProvider>
<SomeComponent1/>
<SomeComponent2/>
<SomeComponentN/>
</SomeReducerProvider>
)
}
This
SyncReducerProviderexample can be checked on line at gmullerb-react-reducer-provider codesandbox:
ThisSyncReducerProviderwith HOC example can be checked on line at gmullerb-react-reducer-provider codesandbox:
AnAsyncReducerProviderexample can be checked on line at gmullerb-react-reducer-provider-async codesandbox:
Examples of use can be looked at basecode-react-ts and test files.
Mappers
2 . Create the AsyncMapperProvider or SyncMapperProvider component to manage the centralized state:
a . Define the initial state.
b . Define the mapper function.
c . Define the Mapper Provider.
SomeMapperProvider.jsx:
import React from "react";
import { SyncMapperProvider } from "react-reducer-provider";
const initialState = 0;
function map(action) {
switch (action) {
case "ACTION1":
return 1;
case "ACTION2":
return -1;
default:
return 0;
}
}
function SomeMapperProvider({ children }) {
return (
<SyncMapperProvider
id="someNamedMapper"
mapper={map}
initialState={initialState}
>
{children}
</SyncMapperProvider>
);
}
export { SomeMapperProvider };3 . Access the state and the dispatcher of the Provider component using the hooks or HOC provided by 'react-reducer-provider':
SomeComponent1.jsx => using useMapper:
import { useMapper } from "react-reducer-provider";
import React from "react";
export default function SomeComponent1() {
const [state, dispatch] = useMapper("someNamedMapper");
return (
<button onClick={() => dispatch("ACTION1")}>
Set to 1 (from {state})!
</button>
);
}SomeComponent2.jsx => using useMapperDispatcher:
import { useMapperDispatcher } from "react-reducer-provider";
import React from "react";
export default function SomeComponent2() {
const dispatch = useMapperDispatcher("someNamedMapper");
return <button onClick={() => dispatch("ACTION2")}>Set to -1!</button>;
}SomeComponentN.jsx => using injectMapperState:
import { injectMapperState } from "react-reducer-provider";
import React from "react";
class SomeComponentN extends React.Component {
render() {
return <div>Current:{this.props.currentState}</div>;
}
}
export default injectMapperState(SomeComponentN, 'currentState')4 . Wrap components which will consume the SomeMapperProvider component:
SomeContainer.jsx:
import SomeComponent1 from "./SomeComponent1";
import SomeComponent2 from "./SomeComponent2";
import SomeComponentN from "./SomeComponentN";
import { SomeMapperProvider } from "./SomeMapperProvider";
import React from "react";
export default function SomeContainer() {
return (
<SomeMapperProvider>
<SomeComponent1 />
<SomeComponent2 />
<SomeComponentN />
</SomeMapperProvider>
);
}
An
SyncMapperProviderexample can be checked on line at gmullerb-react-mapper-provider codesandbox:
AnAsyncMapperProviderexample can be checked on line at gmullerb-react-mapper-provider-async codesandbox:
Examples of use can be looked at test files.
Actuators
2 . Create the ActuatorProvider component to manage a state (or whatever you need, not only state):
a . Define actuator function.
b . Define Actuator Provider.
c. Wrap components which will consume the ActuatorProvider:
SomeContainer.jsx:
import SomeComponent1 from './path/to/SomeComponent1'
import SomeComponent2 from './path/to/SomeComponent2'
import { ActuatorProvider } from 'react-reducer-provider'
import React from 'react'
export function SomeContainer() {
const [state, setState] = React.useState(0)
const actuate = delta => setState(state + delta)
return (
<div>
<ActuatorProvider actuator={actuate}>
<SomeComponent1/>
<SomeComponent2/>
</ActuatorProvider>
Current:{state}
</div>
)
}3 . Access dispatcher of the Provider component using the hooks or HOC provided by 'react-reducer-provider':
SomeComponent1.jsx => using useActuator:
import { useActuator } from 'react-reducer-provider'
import React from 'react'
export function SomeComponent1() {
const dispatch = useActuator()
return (
<button onClick={() => dispatch(+1)}>
Go up!
</button>
)
}SomeComponent2.jsx => using injectActuator:
import { injectActuator } from "react-reducer-provider";
import React from "react";
class SomeComponent2 extends React.Component {
render() {
return (
<button
onClick={() => {
const newState = this.props.dispatch(-1);
console.info(newState);
}}
>
Go down!
</button>
);
}
}
export default injectActuator(SomeComponent2, "dispatch");
This
ActuatorProviderexample can be checked on line at gmullerb-react-actuator-provider codesandbox:
Examples of use can be looked at test files.
Goal
With the introduction of React Hooks, in some way using Flux library1 was deprecated, react-reducer-provider looks to give a quick and easy alternative using hooks to implement Flux with reducers.
- Provides Reducers, but also Mappers and Actuators.
- It allows to use Asynchronous Reducer/Mapper/Dispatcher.
- Reducer/Mapper/Dispatcher can have more parameters/arguments than traditional reducer which have only (state, action).
- Dispatcher returns the new State or a Promise of the new State.
- Actuator allows you to easily introduced centralized state without moving your existing state, i.e. allows you to avoid using a new state container if you already have one.
- Each Reducer/Mapper/Actuators Provider can have a different names, numbers or symbols which allows for easy identification and nesting.
- Provides and Easy way of combining reducer/mapper/actuator functions. through Tags. 2.
- Smaller than other packages with "same" functionality, and no dependencies 3.
- It is ready for Tree Shaking optimization, so you get only what you need from the
react-reducer-providerin the final app bundle 3. - It provides its own type definitions for Typescript and Flow.
- Full Tested, not only focus in coverage, but also in cases and typings: tests, results, coverage and typings tests.
1 Not the Flux architecture.
2 react-redux makes it too complicated.
3 Check and Compare with other solutions at bundlephobia.com.react-reducer-provideris the evolution of react-named-reducer (which is a derivation of react-reducer-context).
You define:
or
or
and then you use them through a:
Prerequisites
At least "react": ">=16.0.0" - React Context => when using HOC, i.e. injectReducer · injectReducerState · injectReducerDispatcher · injectMapper · injectMapperState · injectMapperDispatcher or injectTaggedAny · injectTaggedReducer · injectTaggedReducerState · injectTaggedReducerDispatcher · injectTaggedMapper · injectTaggedMapperState · injectTaggedMapperDispatcher.
"react": ">=16.8.0" - React Hooks => when using hooks, i.e. useReducer · useReducerState · useReducerDispatcher · useMapper · useMapperState · useMapperDispatcher or useTaggedAny · useTaggedReducer · useTaggedReducerState · useTaggedReducerDispatcher · useTaggedMapper · useTaggedMapperState · useTaggedMapperDispatcher.
react-reducer-provideronly enforces"react": ">=16.0.0"inpackage.jsonis up to you to be set which version you need.
Documentation
- Actuators.
ActuatorProvider.- Hooks:
- HOC:
- Singleton.
- Nesting Providers.
- Combining/Blending - Tagged Reducers/Mappers/Actuator.
AsyncTaggedReducerProvider·SyncTaggedReducerProvider·AsyncTaggedMapperProvider·SyncTaggedMapperProvider·TaggedActuatorProvider.useTaggedAny·useTaggedReducer·useTaggedReducerState·useTaggedReducerDispatcher·useTaggedMapper·useTaggedMapperState·useTaggedMapperDispatcher·useTaggedActuator.injectTaggedAny·injectTaggedReducer·injectTaggedReducerState·injectTaggedReducerDispatcher·injectTaggedMapper·injectTaggedMapperState·injectTaggedMapperDispatcher·injectTaggedActuator.
- Typings.
Extras:
CHANGELOG: add information of notable changes for each version here, chronologically ordered (Keep a Changelog).
Contributing
- Use it.
- Share it.
- Give it a Star.
- Propose changes or improvements.
- Report bugs.
License
Remember
- Use code style verification tools => Encourages Best Practices, Efficiency, Readability and Learnability.
- Code Review everything => Encourages Functional suitability, Performance Efficiency and Teamwork.
- If viable, Start testing early => Encourages Reliability and Maintainability.
Additional words
Don't forget:
- Love what you do.
- Learn everyday.
- Learn yourself.
- Share your knowledge.
- Think different!.
- Learn from the past, dream on the future, live and enjoy the present to the max!.
- Enjoy and Value the Quest (It's where you learn and grow).
At life:
- Let's act, not complain.
- Be flexible.
At work:
- Let's give solutions, not questions.
- Aim to simplicity not intellectualism.
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago