我有一个数学算法,想与React分开。 React是该算法内状态的一个视图,不应定义逻辑在算法内的流动方式。另外,由于它是分离的,因此对算法进行单元测试要容易得多。我已经使用类组件(简化)实现了它:
class ShortestPathRenderer extends React.Component {
ShortestPath shortestPath;
public constructor(props) {
this.shortestPath = new ShortestPath(props.spAlgorithm);
this.state = { version: this.shortestPath.getVersion() };
}
render() {
... // Render waypoints from shortestPath
}
onComponentDidUpdate(prevProps) {
if (prevProps.spAlgorithm !== this.props.spAlgorithm) {
this.shortestPath.updateAlgorithm(this.props.spAlgorithm);
}
}
onComponentWillUnmount() {
this.shortestPath = undefined;
}
onAddWayPoint(x) {
this.shortestPath.addWayPoint(x);
// Check if we need to rerender
this.setState({ version: this.shortestPath.getVersion() });
}
}
我该如何使用React钩子来解决这个问题?我在考虑使用useReducer方法。但是,shortestPath变量将是化简器外部的自由变量,并且化简器不再是纯净的,我发现它很脏。因此,在这种情况下,必须在每次更新算法内部状态时复制算法的整个状态,并且必须返回一个新实例,这样效率不高(并迫使算法的逻辑成为反应方式) :
class ShortestPath {
...
addWayPoint(x) {
// Do something
return ShortestPath.clone(this);
}
}
const shortestPathReducer = (state, action) => {
switch (action.type) {
case ADD_WAYPOINT:
return action.state.shortestPath.addWayPoint(action.x);
}
}
const shortestPathRenderer = (props) => {
const [shortestPath, dispatch] = useReducer(shortestPathReducer, new ShortestPath(props.spAlgorithm));
return ...
}
答案 0 :(得分:1)
我会选择这样的东西:
const ShortestPathRenderer = (props) => {
const shortestPath = useMemo(() => new ShortestPath(props.spAlgorithm), []);
const [version, setVersion] = useState(shortestPath.getVersion());
useEffect(() => {
shortestPath.updateAlgorithm(spAlgorithm);
}, [spAlgorithm]);
const onAddWayPoint = (x) => {
shortestPath.addWayPoint(x);
// Check if we need to rerender
setVersion(shortestPath.getVersion());
}
return (
... // Render waypoints from shortestPath
)
}
您甚至可以进一步分离逻辑并创建useShortestPath
钩子:
可重用的状态逻辑:
const useShortestPath = (spAlgorithm) => {
const shortestPath = useMemo(() => new ShortestPath(spAlgorithm), []);
const [version, setVersion] = useState(shortestPath.getVersion());
useEffect(() => {
shortestPath.updateAlgorithm(spAlgorithm);
}, [spAlgorithm]);
const onAddWayPoint = (x) => {
shortestPath.addWayPoint(x);
// Check if we need to rerender
setVersion(shortestPath.getVersion());
}
return [onAddWayPoint, version]
}
代表性部分:
const ShortestPathRenderer = ({spAlgorithm }) => {
const [onAddWayPoint, version] = useShortestPath(spAlgorithm);
return (
... // Render waypoints from shortestPath
)
}
答案 1 :(得分:1)
您只需使用useState挂钩即可在功能模拟中切换基于示例的基于类
function ShortestPathRenderer({ spAlgorithm }) {
const [shortestPath] = useRef(new ShortestPath(spAlgorithm)); // use ref to store ShortestPath instance
const [version, setVersion] = useState(shortestPath.current.getVersion()); // state
const onAddWayPoint = x => {
shortestPath.current.addWayPoint(x);
setVersion(shortestPath.current.getVersion());
}
useEffect(() => {
shortestPath.current.updateAlgorithm(spAlgorithm);
}, [spAlgorithm]);
// ...
}