ReactJS:在再次获取之前清空组件的旧数据

时间:2020-02-04 18:47:11

标签: reactjs react-native fetch react-hooks

我正在从我的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:

  • 由于道具更改而重新渲染第1步(但使用旧数据,因为setItems(null)执行得太晚了)
  • setItems(null)最终执行后第二次重新渲染
  • 提取数据后
  • 第3次重新渲染

我了解我的方法存在的问题。但是我看不到另一种方式。 必须使用钩子。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

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

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

当页面值更改时,将卸载“列表”组件,并呈现一个新组件。新的渲染器中将没有任何以前的数据,因此您将只获得2个渲染器,而不是3个。

这意味着您不必再将先前的数据设置为null

如果执行此操作,则需要在调用useEffect之前检查组件是否仍安装在setItems中,否则,您将尝试在未安装的组件上设置状态。您可以编写:

if(setItems) {
  setItems(data)
}

但是更改关键道具有点麻烦,所以我将研究其他方法来解决您的问题。

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

尽管如此,使用页面更改密钥应该可以。

答案 1 :(得分:0)

use this method  : 

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

     return (
        <ul>
          {items? items.map(item => (
            <li key={item.id}>{item}</li>
          )):"Data is Loading..."}
        </ul>
      )