-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreateDataContext.js
More file actions
98 lines (81 loc) · 2.36 KB
/
Copy pathcreateDataContext.js
File metadata and controls
98 lines (81 loc) · 2.36 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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import React, { createContext, useMemo, useReducer } from 'react';
/**
*
* USAGE
*
*
import createDataContext from './createDataContext';
const locationActions = {
start: (state) => ({
...state,
recording: true
}),
stop: (state) => ({
...state,
recording: false
}),
add: (state, newLocation) => ({
...state,
currentLocation: newLocation.coords,
locations: [...state.locations, newLocation]
})
};
const { Provider, Context } = createDataContext('location', locationActions, {
recording: false,
locations: [],
currentLocation: null
});
const LocationProvider = Provider;
export const LocationContext = Context;
export default LocationProvider;
*
*
*
*/
export default function createDataContext(contextName, actions, initialState){
/**
* a super generic 'reduce' function, that can be used with an 'actions' object
*/
function reduce(currState, { type, payload }){
return (type in actions) ? actions[type](currState, payload) : currState;
}
// simple react context
const Context = createContext();
/**
* this will be a react component, that will wrap the app
*/
const Provider = ({ children }) => {
// initialState is given to useReducer
const [state, dispatch] = useReducer(reduce, initialState);
// methods will be provided to app components,
// only a call to the method with a payload is needed to dispatch an action.
// actionToMethods will be responsible for that
const methods = useMemo(() => actionsToMethods(actions, dispatch), [contextName]);
const ctx = {
state,
methods
};
// wrap children and provide data and dispatch methods
return (
<Context.Provider value={ctx}>
{children}
</Context.Provider>
);
}
return {
Provider,
Context,
}
};
// create an object, where each key corresponds to one action,
// and holds a function that just calls 'dispatch' with the correct arguments
function actionsToMethods(actions, dispatch){
const methods = Object.keys(actions).reduce((allMethods, type) => {
allMethods[type] = (payload) => dispatch({
type,
payload
});
return allMethods;
}, {});
return methods;
}