繁体   English   中英

返回结果时先渲染组件

[英]Render components before others when results are returned

我有一个 function,它从具有四个端点的 API 中获取; 一个返回数据(从另一个 API),另外三个对文本进行一些分析。 我首先调用第一个端点 (/getdata),它返回数据和经过清理的文本属性。 然后我使用干净的文本调用其他三个端点。

我的问题是,这三个分析调用需要相当多的时间才能完成。 我想获取数据,只显示与数据相关的所有组件(不分析),然后在其他 3 个调用完成后(如果可能的话,组件上会有加载 animation 等指示),组件相关对他们来说人口稠密。

我拥有的:

// this is set through a form
const [text, setText] = useState('');

const getData = useCallback(async () => {
    const url = `https://my-api.com/api/getdata?text=${text}`;
    console.log(url);
    const response = await fetch(url);
    const data = await response.json();

    return data;
}, [text]);

const getOtherData = async (data) => {
    const newData = [];
    for (const tweet of data.results) {
      const url1 = `https://my-api.com/api/getsentiment?text=${tweet.clean_text}`;
      const url2 = `https://my-api.com/api/getkeywords?text=${tweet.clean_text}`;
      const url2 = `https://my-api.com/api/gettopics?text=${tweet.clean_text}`;

      const [sentiment, keywords, topic] = await Promise.all([
        await fetch(url1).then((res) => res.json()),
        await fetch(url2).then((res) => res.json()),
        await fetch(url3).then((res) => res.json()),
      ]);

      tweet['sentiment'] = sentiment.sentiment;
      tweet['keywords'] = keywords.keywords;
      tweet['topic'] = topic.topics;

      newData.push(tweet);
    }

    return newData;
};

const handleSubmit = async () => {
    ...
    setLoading(true);

    const data = await getData(); // this is the raw data plus cleaned text

    const newData = await getOtherData(data);
    setData(newData);

    setLoading(false);
};

在没有文本分析的情况下获取数据后,我可能可以设置数据,但我setData以后如何用新分析的数据更新其他组件。 再次设置数据会导致所有内容更新/重新加载,对吗? 我想把每个 state 分开; 一个只包含原始数据(和清理过的文本),另一个包含原始数据+文本分析结果。 这有意义还是有更好的方法?

您可以使用useEffect() 例如:

(这个例子应该被理解为原理的说明。这很可能不是最佳方法,或者甚至可能根本不适用于您的用例。例如,如果数据可以独立于这些加载调用而改变,它将失败,或者例如,如果数据永远不会在这些加载调用之外更改,则loading state 可能是不必要的。您可能还需要考虑使用两个useEffect()块和自定义挂钩

useEffect( () => {

  if( !data && !loading ){   // <-- some condition to check if data is loaded
     setLoading( true );
     getData().then( firstData => {
       setLoading( false );
       setData( firstData );
     });

  } else if( !data.containsNewData && !loading ) { // <-- some condition to check for new data
     setLoading( true );
     getOtherData( data ).then( newData => {
       setLoading( false );
       setData( newData );
     });

  } else {
     // all data is available
  }
}, [ data ]);

暂无
暂无

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

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