-
Notifications
You must be signed in to change notification settings - Fork 138
/
Copy pathreact.js
61 lines (53 loc) · 2.28 KB
/
react.js
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
import { createContext, createElement, Children, useContext, useState, useEffect } from 'react';
import { assign, mapActions, select } from '../util';
const Context = createContext();
/** Wire a component up to the store. Passes state as props, re-renders on change.
* @param {Function|Array|String} mapStateToProps A function mapping of store state to prop values, or an array/CSV of properties to map.
* @param {Function|Object} [actions] Action functions (pure state mappings), or a factory returning them. Every action function gets current state as the first parameter and any other params next
* @returns {Component} ConnectedComponent
* @example
* const Foo = connect('foo,bar')( ({ foo, bar }) => <div /> )
* @example
* const actions = { someAction }
* const Foo = connect('foo,bar', actions)( ({ foo, bar, someAction }) => <div /> )
* @example
* @connect( state => ({ foo: state.foo, bar: state.bar }) )
* export class Foo { render({ foo, bar }) { } }
*/
export function connect(mapStateToProps, actions) {
if (typeof mapStateToProps!=='function') {
mapStateToProps = select(mapStateToProps || []);
}
let boundActions;
return Child => function Wrapper (props) {
const store = useContext(Context);
let [state = mapStateToProps(store ? store.getState() : {}, props), setState] = useState();
boundActions = boundActions || actions ? mapActions(actions, store) : { store };
useEffect(() => {
let update = () => {
let mapped = mapStateToProps(store ? store.getState() : {}, props);
for (let i in mapped) if (mapped[i]!==state[i]) {
state = mapped;
return setState(state);
}
for (let i in state) if (!(i in mapped)) {
state = mapped;
return setState(state);
}
};
return store.subscribe(update);
}, []);
return createElement(Child, assign(assign(assign({}, boundActions), props), state));
};
}
/** Provider exposes a store (passed as `props.store`) into context.
*
* Generally, an entire application is wrapped in a single `<Provider>` at the root.
* @class
* @extends Component
* @param {Object} props
* @param {Store} props.store A {Store} instance to expose via context.
*/
export function Provider (props) {
return createElement(Context.Provider, { value: props.store }, Children.only(props.children));
}