This repository has been archived by the owner on Jun 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathNotifyObservers.react.js
105 lines (92 loc) · 2.9 KB
/
NotifyObservers.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
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
99
100
101
102
103
104
105
import {connect} from 'react-redux';
import {isEmpty} from 'ramda';
import {notifyObservers, updateProps} from '../../actions';
import React from 'react';
import PropTypes from 'prop-types';
/*
* NotifyObservers passes a connected `setProps` handler down to
* its child as a prop
*/
function mapStateToProps(state) {
return {
dependencies: state.dependenciesRequest.content,
paths: state.paths,
};
}
function mapDispatchToProps(dispatch) {
return {dispatch};
}
function mergeProps(stateProps, dispatchProps, ownProps) {
const {dispatch} = dispatchProps;
return {
id: ownProps.id,
children: ownProps.children,
dependencies: stateProps.dependencies,
paths: stateProps.paths,
setProps: function setProps(newProps) {
const payload = {
props: newProps,
id: ownProps.id,
itempath: stateProps.paths[ownProps.id],
};
// Update this component's props
dispatch(updateProps(payload));
// Update output components that depend on this input
dispatch(notifyObservers({id: ownProps.id, props: newProps}));
},
};
}
function NotifyObserversComponent({
children,
id,
paths,
dependencies,
setProps,
}) {
const thisComponentSharesState =
dependencies &&
dependencies.find(
dependency =>
dependency.inputs.find(input => input.id === id) ||
dependency.state.find(state => state.id === id)
);
/*
* Only pass in `setProps` if necessary.
* This allows component authors to skip computing unneeded data
* for `setProps`, which can be expensive.
* For example, consider `hoverData` for graphs. If it isn't
* actually used, then the component author can skip binding
* the events for the component.
*
* TODO - A nice enhancement would be to pass in the actual
* properties that are used into the component so that the
* component author can check for something like
* `subscribed_properties` instead of just `setProps`.
*/
const extraProps = {};
if (
thisComponentSharesState &&
// there is a bug with graphs right now where
// the restyle listener gets assigned with a
// setProps function that was created before
// the item was added. only pass in setProps
// if the item's path exists for now.
paths[id]
) {
extraProps.setProps = setProps;
}
if (!isEmpty(extraProps)) {
return React.cloneElement(children, extraProps);
}
return children;
}
NotifyObserversComponent.propTypes = {
id: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
path: PropTypes.array.isRequired,
};
export default connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(NotifyObserversComponent);