-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSelectorCounters.tsx
More file actions
58 lines (50 loc) · 1.99 KB
/
SelectorCounters.tsx
File metadata and controls
58 lines (50 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { memo } from 'react'
// 1. Import the factory:
import { createSelectorContext } from 'react-selector-context'
import { AppContext, AppContextType } from '../Context'
import { CounterUI } from './CounterUI'
// 2. Wrap the context
// IMPORTANT: Do not forget to add the Provider somewhere at the root of your application.
export const [AppSelectorContext, useSelectorContext] = createSelectorContext(AppContext)
// 3. Selector for counter value and its setter action:
const selectCounter = (context: AppContextType) => ({
counter: context.counter,
setCounter: context.setCounter,
})
// 4. Selector for the other counter value and its setter action:
const selectOtherCounter = (context: AppContextType) => ({
otherCounter: context.otherCounter,
setOtherCounter: context.setOtherCounter,
})
// 5. Optional (if selectors return stable reference) comparison method:
//
// We are selecting multiple values and return new object on each context change.
// We therefore need to tell whether the values are really different.
//
// This is a naive and dirty comparison solution.
// Use `immer` or full equality check of object properties instead.
//
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function customEqual(before: any, after: any) {
try {
return JSON.stringify(before) === JSON.stringify(after)
} catch (e) {
return false
}
}
// 6a. Final UI components:
export const SelectorCounter = memo(() => {
const { setCounter, counter } = useSelectorContext(selectCounter, customEqual)
return (
<CounterUI action={setCounter} label="Counter with Selector" value={counter} />
)
})
SelectorCounter.displayName = 'SelectorCounter'
// 6b. Final UI components:
export const OtherSelectorCounter = memo(() => {
const { otherCounter, setOtherCounter } = useSelectorContext(selectOtherCounter, customEqual)
return (
<CounterUI action={setOtherCounter} label="Other Counter with Selector" value={otherCounter} />
)
})
OtherSelectorCounter.displayName = 'OtherSelectorCounter'