Skip to content

Instantly share code, notes, and snippets.

@derekclair
Forked from keatz55/Editor.js
Created May 31, 2018 07:52
Show Gist options
  • Save derekclair/2a3adfe0076b36aefea39593c4148255 to your computer and use it in GitHub Desktop.
Save derekclair/2a3adfe0076b36aefea39593c4148255 to your computer and use it in GitHub Desktop.
Context API - Simple Tree Structure Example
import React from 'react';
import Paper from '@material-ui/core/Paper';
import uuidv4 from 'uuid/v4';
import TreeContext from './contexts/TreeContext';
import Node from './components/Node';
import NodeEditor from './components/NodeEditor';
class Editor extends React.Component {
state = { nodes: {}, root: {}, selected: null };
componentDidMount = () => {
const rootNode = {
uuid: uuidv4(),
style: {
display: 'flex',
},
children: [],
};
this.setState({
nodes: {
[rootNode.uuid]: rootNode,
},
root: rootNode.uuid,
selected: rootNode.uuid,
});
};
insertNode = (uuid, insert) => {
const { nodes } = this.state;
const node = { ...nodes[uuid] };
node.children.push(insert.uuid);
this.setState({
nodes: {
...nodes,
[node.uuid]: node,
[insert.uuid]: insert,
},
});
};
selectNode = uuid => {
const { selected } = this.state;
if (selected !== uuid) {
this.setState({ selected: uuid });
}
};
updateNode = update => {
const { nodes } = this.state;
this.setState({
nodes: {
...nodes,
[update.uuid]: update,
},
});
};
render() {
const { nodes, root, selected } = this.state;
return (
<TreeContext.Provider
value={{
insertNode: this.insertNode,
nodes,
root,
selected,
selectNode: this.selectNode,
updateNode: this.updateNode,
}}
>
<div>
<div
style={{
flex: 1,
padding: '0 382px 16px 16px',
}}
>
<Node uuid={root} />
</div>
<NodeEditor />
</div>
</TreeContext.Provider>
);
}
}
export default Editor;
import React from 'react';
import Paper from '@material-ui/core/Paper';
import withTree from '../hocs/withTree';
class Node extends React.PureComponent {
render() {
const { uuid, tree } = this.props;
const node = tree.nodes[uuid] || {};
const selected = uuid === tree.selected;
const style = {
...node.style,
padding: '16px',
border: '1px solid #f0f0f0',
};
if (selected) {
style.outlineStyle = 'solid';
style.outlineColor = 'pink';
}
return (
<Paper
square
elevation={1}
style={style}
onClick={e => {
e.preventDefault();
e.stopPropagation();
tree.selectNode(uuid);
}}
>
{node.children &&
node.children.length > 0 &&
node.children.map(uuid => <EnhancedNode uuid={uuid} />)}
</Paper>
);
}
}
const EnhancedNode = withTree(Node);
export default EnhancedNode;
import React from 'react';
const TreeContext = React.createContext({
deleteNode: () => {},
insertNode: () => {},
nodes: {},
root: null,
selected: null,
selectNode: () => {},
updateNode: () => {},
});
export default TreeContext;
import React from 'react';
import TreeContext from '../contexts/TreeContext';
function withTree(Component) {
return function TreeComponent(props) {
return (
<TreeContext.Consumer>
{tree => <Component {...props} tree={tree} />}
</TreeContext.Consumer>
);
};
}
export default withTree;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment