繁体   English   中英

你如何使用 React Hooks 处理外部 state?

[英]How do you handle external state with React Hooks?

我有一个数学算法,我想与 React 分开。 React 将是该算法中 state 的视图,并且不应定义逻辑在算法中的流动方式。 此外,由于它是分开的,因此对算法进行单元测试要容易得多。 我已经使用 class 组件(简化)实现了它:

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 hooks go 关于这个? 我正在考虑使用 useReducer 方法。 但是,shortestPath 变量将成为减速器外部的自由变量,并且减速器不再是纯的,我觉得这很脏。 因此,在这种情况下,算法的整个 state 必须随着算法内部 state 的每次更新而被复制,并且必须返回一个新实例,这不是有效的(并且强制算法的逻辑是 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 ...
}

我会用这样的东西 go :

const ShortestPathRenderer = (props) => {
  const shortestPath = useMemo(() => new ShortestPath(props.spAlgorithm), [props.spAlgorithm]);
  const [version, setVersion] = useState(shortestPath.getVersion());

  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), [spAlgorithm]);
  const [version, setVersion] = useState(shortestPath.getVersion());

  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
  )
}

您可以仅使用 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]);

  // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM