Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gmullerb/react-reducer-context
React Component to manage State through reducers using contexts and hooks.
https://github.com/gmullerb/react-reducer-context
Last synced: 3 days ago
JSON representation
React Component to manage State through reducers using contexts and hooks.
- Host: GitHub
- URL: https://github.com/gmullerb/react-reducer-context
- Owner: gmullerb
- License: mit
- Created: 2019-09-19T17:21:50.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T09:53:10.000Z (over 1 year ago)
- Last Synced: 2024-03-23T11:58:30.589Z (6 months ago)
- Language: JavaScript
- Size: 1.63 MB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 25
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
React Component to manage State through reducers using contexts and hooks
with typings for Typescript and Flow
__________________
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE.txt) ![GitHub package.json version](https://img.shields.io/github/package-json/v/gmullerb/react-reducer-context.svg?logo=npm) ![coverage](https://gitlab.com/gmullerb/react-reducer-context/badges/master/coverage.svg) [![react-reducer-context](https://img.shields.io/badge/npm-react--reducer--context-blue?logo=npm)](https://www.npmjs.com/package/react-reducer-context)
This project is licensed under the terms of the [MIT license](LICENSE.txt).
__________________## Quick Start
1 . Add dependency:
`package.json`:
```json
..
"dependencies": {
"react": "^16.8.0"
"react-reducer-context": "1.0.2",
..
```2 . Create the **`ReducerContext`** component to manage state:
* Define the initial state.
* Define the reducer function.
* Define the `ReducerContext`.**`SomeReducerContext.jsx`**:
```jsx
import React, { createContext } from 'react'
import ReducerContext from 'react-reducer-context'const initialState = 0
function reduce(prevState, action) {
switch (action) {
case 'ACTION1':
return prevState + 1
case 'ACTION2':
return prevState - 1
default:
return prevState
}
}const someReducerContext = createContext(null)
function SomeReducerContext({ children }) {
return (
{children}
)
}export {
someReducerContext as default,
SomeReducerContext
}
```3 . Wrap components which needs the `ReducerContext` component:
`SomeContainer.jsx`:
```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'export default function SomeContainer() {
return (
)
}
```4 . Access the `ReducerContext` component using `'react-reducer-context'` hooks:
* **`useReducerContext`**.
* **`useReducerDispatcher`**.
* **`useReducerState`**.`SomeComponent1.jsx` [1]:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerContext } from 'react-reducer-context'
import React from 'react'export default function SomeComponent1() {
const { state, dispatch } = useReducerContext(someReducerContext)
return (
dispatch('ACTION1')}>
Go up (from {state})!
)
}
````SomeComponent2.jsx` [1]:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerDispatcher } from 'react-reducer-context'
import React from 'react'export default function SomeComponent2() {
const dispatch = useReducerDispatcher(someReducerContext)
return (
dispatch('ACTION2')}>
Go down!
)
}
````SomeComponentN.jsx` [1]:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerState } from 'react-reducer-context'
import React from 'react'export default function SomeComponentN() {
const currentState = useReducerState(someReducerContext)
return (
Current:{currentState}
)
}
```> This example can be checked on line: live at [gmullerb-react-reducer-context demo](https://57esd.csb.app/) and the code is at [gmullerb-react-reducer-context codesandbox](https://codesandbox.io/s/gmullerb-react-reducer-context-57esd?module=%2Fsrc%2FSomeReducerContext.jsx):
[![Edit gmullerb-react-reducer-context](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/gmullerb-react-reducer-context-57esd?module=%2Fsrc%2FSomeReducerContext.jsx)
> [1] Injection can be used in order to improve design, but in favor of quick example this was surrender, look at [Injection](readme/with-injection.md) for injection example.3 . Jump based on requirements into:
* [`ReducerContext` | `useReducerContext` | `useReducerState` | `useReducerDispatcher`](#reference).
* [Nesting](#nesting).
* [Typings](#typings).
* [Prerequisites](#prerequisites).
* Extras:
* [With Injection](readme/with-injection.md).
* [with Flow typings](readme/with-injection-and-flow-typings.md).
* [with Typescript typings](readme/with-injection-and-ts-typings.md).
* [With Actions Creators](readme/with-actions-creators.md)
* [with Flow typings](readme/with-actions-creators-and-flow-typings.md)
* [with Typescript typings](readme/with-actions-creators-and-ts-typings.md)
* [Extending/Developing](readme/developing.md)
* [MIT License](LICENSE.txt)__________________
## 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`](src/main/js/ReducerContext.js) is a React Component which defines a [React Context](https://reactjs.org/docs/context.html) that allows to Manage State using [Flux](http://facebook.github.io/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.![Flux architecture](readme/flux.svg "Flux architecture")
[`ReducerContext`](src/main/js/ReducerContext.js) is a React "Special" Element that requires 3 properties:
* `context`: constitutes the [React Context](https://reactjs.org/docs/context.html) which will be handle by this component.
* use `React.createContext(null)` to create the context.
* `reducer`: a function that will receive the current state and an action to produce a new state.
* internally use [`useReducer` hook](https://reactjs.org/docs/hooks-reference.html#usereducer), which return the current state and a [dispatcher](http://facebook.github.io/flux/docs/dispatcher).
* `initialState`: inception state for the component.```jsx
{children}
```Each `ReducerContext` is equivalent to an Flux stream:
![ReducerContext](readme/react-reducer-context.svg "ReducerContext")
`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 of `useContext` that returns the status and dispatcher.
* which also increase Readability.```jsx
const { state, dispatch } = useReducerContext(someReducerContext)
```e.g.:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerContext } from 'react-reducer-context'
import React from 'react'export default function SomeComponent() {
const { state, dispatch } = useReducerContext(someReducerContext)
return (
dispatch({
type: 'SOME_ACTION',
data: someValue
})}
>
Do something! ({state.someValue})
)
}
```B . Using `useReducerState`:
* `useReducerState` is a "typings-friendly" function that allows to access only state.
* which also increase Readability.```jsx
const state = useReducerState(someReducerContext)
```e.g.:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerState } from 'react-reducer-context'
import React from 'react'export default function SomeComponent() {
const state = useReducerState(someReducerContext)
return (
Some Value: ({state.someValue})
)
}
```C . Using `useReducerDispatcher`:
* `useReducerDispatcher` is a "typings-friendly" function that allows to access only the dispatcher.
* which also increase Readability.```jsx
const dispatch = useReducerDispatcher(someReducerContext)
```e.g.:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import { useReducerDispatcher } from 'react-reducer-context'
import React from 'react'export default function SomeComponent() {
const dispatch = useReducerDispatcher(someReducerContext)
return (
dispatch({
type: 'SOME_ACTION',
data: someValue
})}
>
Do something!
)
}
```D . Using "old" traditional [`useContext`](https://reactjs.org/docs/hooks-reference.html#usecontext):
```jsx
const [state, dispatch] = useContext(someReducerContext)
```e.g.:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import React, { useContext } from 'react'export default function SomeComponent() {
const [state, dispatch] = useContext(someReducerContext)
return (
dispatch({
type: 'SOME_ACTION',
data: someValue
})}
>
Do something! ({state.someValue})
)
}
```E . Using [`Context.Consumer`](https://reactjs.org/docs/context.html#contextconsumer):
```jsx
{
([state, dispatch]) => (
..
)
}
```e.g.:
```jsx
import someReducerContext from '../path/to/SomeReducerContext'
import React, { useContext } from 'react'export default function SomeComponent() {
return (
{
([state, dispatch]) => (
dispatch({
type: 'SOME_ACTION',
data: someValue
})}
>
Do something! ({state.someValue})
)
}
)
}
```> There is another way using [`contextType`](https://reactjs.org/docs/context.html#classcontexttype), but is not functional approach, so it is not exposed.
### Nesting
Based on [React Context](https://reactjs.org/docs/context.html), `ReducerContext` can be nested in layers, in order to have several nested Reducer/State.
```jsx
{someChildren}
{moreChildren}
````moreChildren` can access the State and the Dispatcher of the ReducerContext1 plus the State and the Dispatcher of the ReducerContextN.
![Nested ReducerContext](readme/nested-reducer-context.svg "Nested ReducerContext")
### 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`](src/main/js/ReducerContext.js.flow).
* Typescript: [`ReducerContext.d.ts`](src/main/js/ReducerContext.d.ts).Both provide the following types:
* `ReducerContext`: specifies the Function React Component structure.
* `ReducerContextProps`: defines the properties receive the `ReducerContext`.
* `ReducerContextDefaultValue`: specifies the type of the `React.Context` when created.
* Essentially is a `ReducerContextValue` which also allows a `null` value, which is required when creating the context.
* If required, this type should be use only when creating the `ReducerContext`.
* `ReducerContextValue`: defines the type of the value contained in the `React.Context`.
* This type should be for using the created `ReducerContext` (that never going to be null).
* `ReducerContextInterface`: defines the type of the value return by `useReducerContext`.
* `Dispatcher`: 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`:
```jsx
..const initialState: number = 0
function reduce(prevState: number, action: string): number {
switch (action) {
case 'ACTION1':
return prevState + 1
case 'ACTION2':
return prevState - 1
default:
return prevState
}
}const someReducerContext: Context> = createContext(null)
..
```
`SomeComponent.jsx` or `SomeComponent.tsx`:
```jsx
..
const { state, dispatch }: ReducerContextInterface = useReducerContext(someReducerContext)
..
```or
```jsx
..
const dispatch: Dispatcher = useReducerDispatcher(someReducerContext)
..
```or
```jsx
..
const state: number = useReducerState(someReducerContext)
..
```* A more "complete" example with Flow can be seen at: [`typingTest.jsx`](src/test/typings/flow/typingTest.jsx).
* A more "complete" example with Typescript can be seen at: [`typingTest.tsx`](src/test/typings/ts/typingTest.tsx).> Initial example with Flow typings can be checked on line: live at [gmullerb-react-reducer-context-flow demo](https://7ubs7.csb.app/) and the code is at [gmullerb-react-reducer-context-flow codesandbox](https://codesandbox.io/s/gmullerb-react-reducer-context-flow-7ubs7?module=%2Fsrc%2FSomeReducerContext.jsx):
[![Edit gmullerb-react-reducer-context](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/gmullerb-react-reducer-context-flow-7ubs7?module=%2Fsrc%2FSomeReducerContext.jsx)
> Initial example with Typescript typings can be checked on line: live at [gmullerb-react-reducer-context-ts demo](https://kwqir.csb.app/) and the code is at [gmullerb-react-reducer-context-ts codesandbox](https://codesandbox.io/s/gmullerb-react-reducer-context-ts-kwqir?module=%2Fsrc%2FSomeReducerContext.tsx):
[![Edit gmullerb-react-reducer-context-ts](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/gmullerb-react-reducer-context-ts-kwqir?module=%2Fsrc%2FSomeReducerContext.tsx)
> [1] Only the usual Flow or Typescript configuration (e.g. no need for @types).__________________
### Prerequisites
* [React Hooks](https://reactjs.org/docs/hooks-overview.html) => [`"react": "^16.8.0"`](https://www.npmjs.com/package/react).
__________________
## Extending/Developing
[Developing](readme/developing.md)
## Documentation
* [`CHANGELOG.md`](CHANGELOG.md): add information of notable changes for each version here, chronologically ordered [1].
> [1] [Keep a Changelog](http://keepachangelog.com)
## License
[MIT License](LICENSE.txt)
__________________## 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.