refactor(state): use useReducer

This commit is contained in:
moklick
2019-07-16 12:11:35 +02:00
parent 52241d2be8
commit 17036d2ebd
8 changed files with 171 additions and 113 deletions
+12 -88
View File
@@ -1,123 +1,47 @@
import React, { createContext, useState, useEffect } from 'react';
import React, { createContext, useState, useEffect, useReducer } from 'react';
import PropTypes from 'prop-types';
import { zoomIdentity } from 'd3-zoom';
import isEqual from 'lodash.isequal';
import { getBoundingBox } from '../graph-utils';
import { reducer, initialState } from '../state';
import { setNodes, setEdges } from '../state/actions';
export const GraphContext = createContext({});
export const Provider = (props) => {
const {
nodes: initNodes,
edges: initEdges,
onNodeClick,
children
} = props;
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const [d3ZoomState, initD3ZoomState] = useState({
zoom: null, selection: null, initialised: false
});
const [nodes, setNodes] = useState(initNodes);
const [edges, setEdges] = useState(initEdges);
const [transform, setTransform] = useState({ x: 0, y: 0, k: 1 });
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
const nextNodes = props.nodes.map(propNode => {
const existingNode = nodes.find(n => n.data.id === propNode.data.id);
const existingNode = state.nodes.find(n => n.data.id === propNode.data.id);
if (existingNode) {
return Object.assign(propNode, existingNode);
}
return propNode;
});
const nodesChanged = !isEqual(nodes, nextNodes);
const edgesChanged = !isEqual(edges, props.edges);
const nodesChanged = !isEqual(state.nodes, nextNodes);
const edgesChanged = !isEqual(state.edges, props.edges);
if (nodesChanged) {
setNodes(nextNodes);
dispatch(setNodes(nextNodes));
}
if (edgesChanged) {
setEdges(props.edges);
dispatch(setEdges(props.edges));
}
});
const updateNodeData = (nodeId, updateData) => {
const updatedNodes = nodes.map((n) => {
if (n.data.id === nodeId) {
n.data = {
...n.data,
...updateData
};
}
return n;
});
setNodes(updatedNodes);
};
const updateNodePos = (nodeId, pos) => {
const updatedNodes = nodes.map((n) => {
if (n.data.id === nodeId) {
n.position = pos;
}
return n;
});
setNodes(updatedNodes);
};
const updateTransform = (nextTransform) => {
setTransform({
k: Math.round(nextTransform.k * 1000) / 1000,
x: nextTransform.x,
y: nextTransform.y
});
};
const fitView = () => {
const bounds = getBoundingBox(nodes);
const k = Math.min(width, height) / Math.max(bounds.width, bounds.height);
const boundsCenterX = bounds.x + (bounds.width / 2);
const boundsCenterY = bounds.y + (bounds.height / 2);
const translate = [(width / 2) - (boundsCenterX * k), (height / 2) - (boundsCenterY * k)];
const initialTransform = zoomIdentity.translate(translate[0], translate[1]).scale(k);
d3ZoomState.selection.call(d3ZoomState.zoom.transform, initialTransform);
};
const updateSize = (size) => {
setWidth(size.width);
setHeight(size.height);
};
const getNodes = () => {
return nodes;
}
const graphContext = {
width,
height,
updateSize,
d3ZoomState,
initD3ZoomState,
nodes,
setNodes,
getNodes,
edges,
setEdges,
updateNodeData,
updateNodePos,
transform,
updateTransform,
onNodeClick,
fitView
state,
dispatch
};
return (