首页 > 解决方案 > ReactJS:在再次获取之前清空组件的旧获取数据

问题描述

我正在从我的 React 组件中获取远程数据。当数据准备好时,子组件就会被渲染。在加载数据时,会显示“数据正在加载……”文本。

当组件因props更改而第二次渲染时,我将之前的数据设置为null,以显示正在加载新数据。

const List = (props) => {
  const [items, setItems] = useState(null);

  useEffect(() => {  
    setItems(null);

    fetch(`http://some_url_to_fetch_items.com?PAGE=${props.page}`)
    .then((data) => {
       setItems(data);
    })   
  }, [props.page]);

  if (!items) {
    return "Data is loading ......."
  }

  return (
    <ul>
      {items.map(item => (
        <li>{item}</li>
      ))}
    </ul>
  )
}

这种方法的问题是,当第二次渲染组件时,setItems(null);代码并没有立即执行(可能是因为useEffect异步执行)并且组件重新渲染了 3 次,而不是预期的 2 次:

我明白我的方法有什么问题。但我没有看到其他方法。必须使用钩子。

有任何想法吗?

标签: reactjsreact-nativefetchreact-hooks

解决方案


一个快速的解决方法是在您的列表中添加一个关键道具:

<List key={page} page={page} />

当 page 的值发生变化时,List 组件将被卸载,并呈现一个新的组件。新的将没有任何以前的数据,因此您只会获得 2 个渲染而不是 3 个。

这意味着您不必再设置以前的数据null

如果您这样做,您需要useEffect在调用之前检查该组件是否仍然安装在您的组件中setItems,否则您将尝试在未安装的组件上设置状态。你可以写:

if(setItems) {
  setItems(data)
}

不过,更改密钥道具有点麻烦,所以我会研究其他方法来解决您的问题。

也许您应该将数据传递到列表中,而不是列表负责获取数据,并且将页面状态和数据都包含在父组件中?

不过现在,使用页面更改密钥应该可以工作。


推荐阅读