Skip to content

Commit 006a69c

Browse files
docs: update readme
1 parent 147779a commit 006a69c

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

README.md

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
# @nexpy/react-easy-context-api
2+
3+
[![npm](https://img.shields.io/npm/v/@nexpy/react-easy-context-api)](https://www.npmjs.com/package/@nexpy/react-easy-context-api)
4+
[![size](https://img.shields.io/bundlephobia/minzip/@nexpy/react-easy-context-api)](https://bundlephobia.com/result?p=@nexpy/react-easy-context-api)
5+
6+
## Introduction
7+
8+
Many times when using the React Context API we create unnecessary repetitive and extensive code.
9+
10+
And, React Context and useContext is often used to avoid prop drilling,
11+
however it's known that there's a performance issue.
12+
When a context value is changed, all components that useContext
13+
will re-render.
14+
15+
To solve this issue,
16+
[useContextSelector](https://github.com/reactjs/rfcs/pull/119)
17+
is proposed and later proposed
18+
[Speculative Mode](https://github.com/reactjs/rfcs/pull/150)
19+
with context selector support.
20+
This library provides an easy way to build and use the Context API with these issues fixed.
21+
22+
This package is constructed above the [use-context-selector](https://github.com/dai-shi/use-context-selector).
23+
24+
## Install
25+
26+
This package requires some peer dependencies, which you need to install by yourself.
27+
28+
```bash
29+
yarn add @nexpy/react-easy-context-api scheduler
30+
```
31+
32+
Notes for library authors:
33+
34+
Please do not forget to keep `"peerDependencies"` and
35+
note instructions to let users to install peer dependencies.
36+
37+
## Technical memo
38+
39+
To make it work like original React context, it uses
40+
[useReducer cheat mode](https://overreacted.io/a-complete-guide-to-useeffect/#why-usereducer-is-the-cheat-mode-of-hooks) intentionally.
41+
It also requires `useContextUpdate` to behave better in Concurrent Mode.
42+
(You don't need to use it in Legacy Mode.)
43+
44+
## Usage
45+
46+
```tsx
47+
// cats-context.tsx
48+
import { useState, FC } from 'react'
49+
50+
import { createContext } from '@nexpy/react-easy-context-api'
51+
52+
type MyContext = {
53+
pettedCats: number
54+
currentCats: number
55+
}
56+
57+
const { useSelector, Provider } = createContext<MyContext>({
58+
pettedCats: 0,
59+
currentCats: 0,
60+
})
61+
62+
const CatsProvider: FC = ({ children }) => {
63+
const [pettedCats, setPettedCats] = useState(0)
64+
const [currentCats, setCurrentCats] = useState(0)
65+
66+
// ... your context logic :)
67+
68+
return (
69+
<Provider
70+
value={{
71+
pettedCats,
72+
currentCats,
73+
}}
74+
>
75+
{children}
76+
</Provider>
77+
)
78+
}
79+
80+
export { CatsProvider, useSelector }
81+
82+
// ... in your components
83+
const CatsPetted = () => {
84+
const catsPettedNumber = useSelector(state => state.pettedCats)
85+
86+
return <p>Petted cats: {catsPettedNumber}</p>
87+
}
88+
89+
const CurrentCats = () => {
90+
const currentCatsNumber = useSelector(state => state.currentCats)
91+
92+
return <p>Current cats: {currentCatsNumber}</p>
93+
}
94+
95+
const App = () => (
96+
<CatsProvider>
97+
<CatsPetted />
98+
<CurrentCats />
99+
</CatsProvider>
100+
)
101+
```
102+
103+
## API
104+
105+
### createContext
106+
107+
This creates a special context.
108+
109+
#### Parameters
110+
111+
- `defaultValue` **Value**
112+
113+
#### Examples
114+
115+
```ts
116+
import { createContext } from '@nexpy/react-easy-context-api'
117+
118+
type PersonContext = {
119+
firstName: string
120+
familyName: string
121+
}
122+
123+
const PersonContext = createContext<PersonContext>({ firstName: '', familyName: '' })
124+
```
125+
126+
### Returns:
127+
128+
#### useSelector
129+
130+
This hook returns context selected value by selector.
131+
132+
It will trigger re-render if only the selected value is referentially changed.
133+
134+
The selector should return referentially equal result for same input for better performance.
135+
136+
##### Parameters
137+
138+
- `selector` **function (value: Value): Selected**
139+
140+
##### Examples
141+
142+
```tsx
143+
const MyComponent = () => {
144+
const firstName = PersonContext.useSelector(state => state.firstName)
145+
146+
return <p>{firstName}</p>
147+
}
148+
```
149+
150+
#### useContext
151+
152+
This hook returns the entire context value.
153+
Use this instead of React.useContext for consistent behavior.
154+
155+
##### Examples
156+
157+
```tsx
158+
const MyComponent = () => {
159+
const person = PersonContext.useContext()
160+
// ...
161+
}
162+
```
163+
164+
#### useContextUpdate
165+
166+
This hook returns an update function that accepts a thunk function.
167+
168+
Use this for a function that will change a value in
169+
[Concurrent Mode](https://reactjs.org/docs/concurrent-mode-intro.html).
170+
Otherwise, there's no need to use this hook.
171+
172+
##### Examples
173+
174+
```tsx
175+
const MyComponent = () => {
176+
const update = PersonContext.useContextUpdate()
177+
178+
update(() => setState(...));
179+
// ...
180+
}
181+
```
182+
183+
#### BridgeProvider
184+
185+
This is a Provider component for bridging multiple react roots.
186+
187+
#### Context
188+
189+
The special context created by createContext hook.
190+
191+
#### Provider
192+
193+
The provider you need to use to apply the context.
194+
195+
##### Parameters
196+
197+
- `$0` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**
198+
- `$0.context`
199+
- `$0.value`
200+
- `$0.children`
201+
202+
##### Examples
203+
204+
```tsx
205+
import { createContext } from '@nexpy/react-easy-context-api'
206+
207+
type PersonContext = {
208+
firstName: string
209+
familyName: string
210+
}
211+
212+
const { Context, useBridgeValue, BridgeProvider } = createContext<PersonContext>({
213+
firstName: '',
214+
familyName: '',
215+
})
216+
217+
const App = () => {
218+
const valueToBridge = useBridgeValue()
219+
220+
return (
221+
<>
222+
<BridgeProvider context={Context} value={valueToBridge}>
223+
{children}
224+
</BridgeProvider>
225+
</>
226+
)
227+
}
228+
```
229+
230+
#### useBridgeValue
231+
232+
This hook return a value for BridgeProvider.
233+
234+
## Limitations
235+
236+
- In order to stop propagation, `children` of a context provider has to be either created outside of the provider or memoized with `React.memo`.
237+
- Provider trigger re-renders only if the context value is referentially changed.
238+
- Neither context consumers or class components are supported.
239+
- The [stale props](https://react-redux.js.org/api/hooks#stale-props-and-zombie-children) issue can't be solved in userland.
240+
- Tearing is only avoided if all consumers get data using `useSelector`. If you use both props and selector to pass the same data, they may provide inconsistence data for a brief moment.
241+
242+
## Examples
243+
244+
[See this example file](https://github.com/nexpy-io/react-easy-context-api/blob/main/examples/cats.md).

0 commit comments

Comments
 (0)