React Component to manage State through reducers using contexts and hooks
with typings for Typescript and Flow
This project is licensed under the terms of the MIT license.
Quick Start
1 . Add dependency:
package.json
:
.. "dependencies":
2 . Create the ReducerContext
component to manage state:
- Define the initial state.
- Define the reducer function.
- Define the
ReducerContext
.
SomeReducerContext.jsx
:
import React createContext from 'react'import ReducerContext from 'react-reducer-context' const initialState = 0 { switch action case 'ACTION1': return prevState + 1 case 'ACTION2': return prevState - 1 default: return prevState } const someReducerContext = { return <ReducerContext = = = > children </ReducerContext> }
3 . Wrap components which needs the ReducerContext
component:
SomeContainer.jsx
:
import SomeComponent1 from './path/to/SomeComponent1'import SomeComponent2 from './path/to/SomeComponent2'import SomeComponentN from './path/to/SomeComponentN'import SomeReducerContext from '../path/to/SomeReducerContext'import React from 'react' { return <SomeReducerContext> <SomeComponent1/> <SomeComponent2/> <SomeComponentN/> </SomeReducerContext> }
4 . Access the ReducerContext
component using 'react-reducer-context'
hooks:
useReducerContext
.useReducerDispatcher
.useReducerState
.
SomeComponent1.jsx
[1]:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerContext from 'react-reducer-context'import React from 'react' { const state dispatch = return <button => Go ! </button> }
SomeComponent2.jsx
[1]:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerDispatcher from 'react-reducer-context'import React from 'react' { const dispatch = return <button => Go down! </button> }
SomeComponentN.jsx
[1]:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerState from 'react-reducer-context'import React from 'react' { const currentState = return <div> Current:currentState </div> }
This example can be checked on line: live at gmullerb-react-reducer-context demo and the code is at gmullerb-react-reducer-context codesandbox:
[1] Injection can be used in order to improve design, but in favor of quick example this was surrender, look at Injection for injection example.
3 . Jump based on requirements into:
ReducerContext
|useReducerContext
|useReducerState
|useReducerDispatcher
.- Extending/Developing
- MIT License
Goal
With the introduction of React Hooks, in some way using Flux library[1] was deprecated, react-reducer-context looks to give a quick and easy alternative using hooks to implement Flux with reducers, with typings for Typescript and Flow.
[1] Not the Flux architecture.
ReducerContext
| useReducerContext
| useReducerState
| useReducerDispatcher
ReducerContext
is a React Component which defines a React Context that allows to Manage State using Flux, an application architecture that handles application states in a unidirectional way.
- Flux is composed basically with:
- Stores: keeps states of the app (or components).
- Reducer: function that changes the State based on an Action and the previous State.
- Actions: triggers changes in Store.
- Dispatcher: sends Actions to the Store.
- Mainly the bridge between the Store and Components.
- Stores: keeps states of the app (or components).
ReducerContext
is a React "Special" Element that requires 3 properties:
context
: constitutes the React Context which will be handle by this component.- use
React.createContext(null)
to create the context.
- use
reducer
: a function that will receive the current state and an action to produce a new state.- internally use
useReducer
hook, which return the current state and a dispatcher.
- internally use
initialState
: inception state for the component.
<ReducerContext = = = > children </ReducerContext>
Each ReducerContext
is equivalent to an Flux stream:
children
elements will be able to access the State and Dispatcher.
There are different ways of doing this:
A . Using useReducerContext
:
useReducerContext
is a "typings-friendly" version ofuseContext
that returns the status and dispatcher.- which also increase Readability.
const state dispatch =
e.g.:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerContext from 'react-reducer-context'import React from 'react' { const state dispatch = return <button = > Do something! statesomeValue </button> }
B . Using useReducerState
:
useReducerState
is a "typings-friendly" function that allows to access only state.- which also increase Readability.
const state =
e.g.:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerState from 'react-reducer-context'import React from 'react' { const state = return <div> Some Value: statesomeValue </div> }
C . Using useReducerDispatcher
:
useReducerDispatcher
is a "typings-friendly" function that allows to access only the dispatcher.- which also increase Readability.
const dispatch =
e.g.:
import someReducerContext from '../path/to/SomeReducerContext'import useReducerDispatcher from 'react-reducer-context'import React from 'react' { const dispatch = return <button = > Do something! </button> }
D . Using "old" traditional useContext
:
const state dispatch =
e.g.:
import someReducerContext from '../path/to/SomeReducerContext'import React useContext from 'react' { const state dispatch = return <button = > Do something! statesomeValue </button> }
E . Using Context.Consumer
:
<someReducerContext.Consumer> state dispatch </someReducerContext.Consumer>
e.g.:
import someReducerContext from '../path/to/SomeReducerContext'import React useContext from 'react' { return <someReducerContext.Consumer> state dispatch <button = > Do something! statesomeValue </button> </someReducerContext.Consumer> }
There is another way using
contextType
, but is not functional approach, so it is not exposed.
Nesting
Based on React Context, ReducerContext
can be nested in layers, in order to have several nested Reducer/State.
<ReducerContext = = = > someChildren <ReducerContext = = = > moreChildren </ReducerContext> </ReducerContext>
moreChildren
can access the State and the Dispatcher of the ReducerContext1 plus the State and the Dispatcher of the ReducerContextN.
Typings
react-reducer-context
defines typings for Flow and Typescript:
- Any can be used without an "special" [1] configuration.
- Typings definitions are located together with source files:
- Flow:
ReducerContext.js.flow
. - Typescript:
ReducerContext.d.ts
.
- Flow:
- Typings definitions are located together with source files:
Both provide the following types:
ReducerContext<STATE, ACTION>
: specifies the Function React Component structure.ReducerContextProps<STATE, ACTION>
: defines the properties receive theReducerContext
.ReducerContextDefaultValue<STATE, ACTION>
: specifies the type of theReact.Context
when created.- Essentially is a
ReducerContextValue<STATE, ACTION>
which also allows anull
value, which is required when creating the context. - If required, this type should be use only when creating the
ReducerContext
.
- Essentially is a
ReducerContextValue<STATE, ACTION>
: defines the type of the value contained in theReact.Context
.- This type should be for using the created
ReducerContext
(that never going to be null).
- This type should be for using the created
ReducerContextInterface<STATE, ACTION>
: defines the type of the value return byuseReducerContext
.Dispatcher<ACTION>
: defines the function that receives the action that triggers the change of the state.
STATE
: State type.
ACTION
: Action type.
E.G.:
SomeReducerContext.jsx
or SomeReducerContext.tsx
:
const initialState: number = 0 : number { switch action case 'ACTION1': return prevState + 1 case 'ACTION2': return prevState - 1 default: return prevState } const someReducerContext: Context<ReducerContextDefaultValue<number string>> =
SomeComponent.jsx
or SomeComponent.tsx
:
const state dispatch : ReducerContextInterface<number string> =
or
const dispatch: Dispatcher<string> =
or
const state: number =
- A more "complete" example with Flow can be seen at:
typingTest.jsx
. - A more "complete" example with Typescript can be seen at:
typingTest.tsx
.
Initial example with Flow typings can be checked on line: live at gmullerb-react-reducer-context-flow demo and the code is at gmullerb-react-reducer-context-flow codesandbox:
Initial example with Typescript typings can be checked on line: live at gmullerb-react-reducer-context-ts demo and the code is at gmullerb-react-reducer-context-ts codesandbox:
[1] Only the usual Flow or Typescript configuration (e.g. no need for @types).
Prerequisites
Extending/Developing
Documentation
CHANGELOG.md
: add information of notable changes for each version here, chronologically ordered [1].
[1] Keep a Changelog
License
Remember
- Use code style verification tools => Encourages Best Practices, Efficiency, Readability and Learnability.
- Start testing early => Encourages Reliability and Maintainability.
- Code Review everything => Encourages Functional suitability, Performance Efficiency and Teamwork.
Additional words
Don't forget:
- Love what you do.
- Learn everyday.
- Learn yourself.
- Share your knowledge.
- Learn from the past, dream on the future, live and enjoy the present to the max!.
At life:
- Let's act, not complain.
- Be flexible.
At work:
- Let's give solutions, not questions.
- Aim to simplicity not intellectualism.