【问题标题】:REACT - How to call dependent async operations efficientREACT - 如何有效地调用依赖异步操作
【发布时间】:2020-12-18 19:12:49
【问题描述】:

所以我有一个钩子,我有一个方法可以通过 id 调用统计信息,还有一个方法可以调用可用统计信息列表。

我想首先调用统计列表,然后通过第一个响应中第一个项目的 id 调用实际的统计数据。看起来有点像。像这样:

挂钩

const useMapStatistics = () => {
  const [selectedStatistics, setSelectedStatistics] = useState(null); // maybe use a useRef here ?
  const [allMapStatistics, setAllMapStatistics] = useState([]);
  const [geoJSON, setGeoJSON] = useState({
    type: "",
    features: [],
  });

  const fetchMapStatisticsById = useCallback((type) => {
      getMapStatisticsById({ type })
        .then((result) => setGeoJSON(result));
    },
    []
  );

  const fetchInitialMapStatistics = useCallback(() => {
    getMapStatisticsList().then((list) => {
        setAllMapStatistics(list.statistics);
        setSelectedStatistics(list.statistics[0]);
        return list.statistics[0];
      })
      .then((type) => fetchMapStatisticsById(type));
  }, [fetchMapStatisticsById]);

  useEffect(() => {
    fetchInitialMapStatistics();
  }, []);

  return {
    geoJSON,
    allMapStatistics,
    selectedStatistics,
    fetchMapStatisticsById,
    fetchInitialMapStatistics,
  };
};

现在我问自己这是否是执行此操作的最有效方法?我还尝试使用 selectedStatistics 状态执行fetchMapStatisticsById,如下所示:

  const fetchMapStatisticsById = useCallback(() => {
  getMapStatisticsById({ type: selectedStatistics }) // selectedStatistics is null
    .then(result =>  setGeoJSON(result));
  }, [selectedStatistics]);

但这不起作用,因为在 react 中设置状态是异步发生的(selectedStatistics 为空)。所以我想知道通过 id 获取统计信息的状态是否会更好(这对我不起作用)或者只是将统计信息 id 作为参数传递给 useCallback 函数?还可以选择将 selectedStatistics 放在 useRef 中,这将同步更改。这也是一种选择,还是这种反模式?

【问题讨论】:

  • 只需将其包装在 if (selectedStatistics != null) 中,以防止在尚未加载统计信息时在初始效果调用中获取。

标签: javascript reactjs promise react-hooks


【解决方案1】:

您提出了两种完成工作的方法,您想知道哪种方法更好,这取决于您的目的,因为您可能想知道它们不一样。

您可以这样做,但这意味着地图统计信息的更改只会在调用 fetchInitialMapStatistics 时发生在初始渲染上。这意味着更改您的 selectedStatisticsId 不会导致 mapStatisits 和 GeoJSON 更改,这可能不是您想要的。

 const fetchInitialMapStatistics = useCallback(() => {
    getMapStatisticsList().then((list) => {
        setAllMapStatistics(list.statistics);
        setSelectedStatistics(list.statistics[0]);
        return list.statistics[0];
      })
      .then((type) => fetchMapStatisticsById(type));
  }, [fetchMapStatisticsById]);

另一方面,您可以这样做,这意味着只要 selectedId 更改您想要更改 geoJSON 的状态(这可能是您想要的),作为旁注,您还应该在选择 id 时实现转换状态变化,类似于装载机。

const fetchInitialMapStatistics = useCallback(() => {
    getMapStatisticsList().then((list) => {
        setAllMapStatistics(list.statistics);
        setSelectedStatistics(list.statistics[0]);
        return list.statistics[0];
      })
     
  }, []);

useEffect(() => {
    if (selectedStatistics !== null) {
       // anyway its better here to send the selected id as a param and not take it from state
       // its better for at least three reasons that i can think of now
       // - more readable code
       // - easier code to test
       // - your code is less subject to bugs related to misunderstanding of what the selectedId is
       fetchMapStatisticsById(selectedStatistics);
    }
  }, [selectedStatistics]);

【讨论】:

  • 感谢有用的提示(也关于装载机)。但是您提供的示例没有任何意义。^^ 在 useEffect 中,您将 fetchInitialMapStatistics 包装在一个 if 案例中,如果不调用此函数,这永远不会是真的。收听 selectedStatistics 的变化对那个eiter没有帮助。
  • @MarcoLe 哦,我明白你的意思了,我没有使用正确的函数名称,所以我使用了 fetchInitialMapStatistics 而不是 fetchMapStatisticsById,我编辑了我的示例。当然我的代码 sn-p 没有完整的代码,我假设您已经有一个调用 fetchInitialMapStatistics 的 useEffect,您将 selectedStatistics 设置为 null 以外的值。
猜你喜欢
  • 2020-10-30
  • 2020-02-16
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 2022-08-24
  • 2015-09-13
  • 2021-12-05
相关资源
最近更新 更多