-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexample.context-selector.tsx
More file actions
55 lines (47 loc) · 1.98 KB
/
Copy pathexample.context-selector.tsx
File metadata and controls
55 lines (47 loc) · 1.98 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
import { memo, useCallback, useMemo } from "react";
import { createContext as createSelectorContext, useContextSelector } from "use-context-selector";
import type { ExampleStore } from "./example";
const StoreCtx = createSelectorContext<ExampleStore>(undefined!);
const Row = memo((props: { index: number }) => {
// you should use multiple useContextSelector for proper work
const value = useContextSelector(StoreCtx, ([data, setData]) => data[props.index]);
const setData = useContextSelector(StoreCtx, ([data, setData]) => setData);
const handleChange = useCallback((evt: any) => {
setData(prevData => [
...prevData.slice(0, props.index),
+evt.target.value,
...prevData.slice(props.index + 1),
])
}, [props.index]);
return (
<div>
{Math.random().toFixed(2)}
<input type="number" value={value} onChange={handleChange} />
</div>
);
});
const ListSum = memo(() => {
const sum = useContextSelector(StoreCtx, ([data]) => data.reduce((sum, x) => sum + x, 0));
return <div>{sum}</div>
});
const ListRenderer = memo((props: { length: number }) => (
<>{Array.from({ length: props.length }).map((_, i) => (
<Row key={i} index={i} />
))}</>
));
export const ExampleContextSelector = (props: { store: ExampleStore }) => {
const [state] = props.store;
return (
<StoreCtx.Provider value={props.store}>
<div>if row will be updated, random values will change</div>
<pre>{`
// you should use multiple useContextSelector for proper work
// and there is no other way as it compares by reference
const value = useContextSelector(StoreCtx, ([data, setData]) => data[props.index]);
const setData = useContextSelector(StoreCtx, ([data, setData]) => setData);
`}</pre>
<ListSum />
<ListRenderer length={state.length} />
</StoreCtx.Provider>
);
};