javascript - 你如何使用 React Hooks 处理外部状态?
问题描述
我有一个数学算法,我想与 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 变量将成为减速器外部的自由变量,并且减速器不再是纯的,我觉得这很脏。所以在这种情况下,算法的整个状态必须随着算法内部状态的每次更新而被复制,并且必须返回一个新的实例,这不是有效的(并且强制算法的逻辑是 React-way) :
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 ...
}
解决方案
我会用这样的东西:
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
)
}
推荐阅读
- android - Appium - 无法在字段中输入文本
- java - 我正在制作一个应用程序,我需要使用 Parcelable 接口,但面临问题,不知道如何实现它
- c# - C# 我应该将 bool 初始化为 false 还是应该在 else 语句中将其设为 false?最佳实践?
- r - 使用 R 在逻辑回归中将交互的特定组合作为变量
- python - Qtreewidget Pyqt5如何恢复正常?
- microsoft-graph-api - 团队 listChannel Graph API 导致“未经授权的错误 - “无法执行 Aad 后端请求 GetUsersByObjectIdsRequest”
- html - 如何使具有定位元素的块响应?
- python - 尝试从 Gmail 中阅读具有特定主题的电子邮件
- angular - 找不到自定义角度库中使用的模块
- r - 如何在矩阵中按行将 0 分配给最小值(以快速/有效的方式)?