【问题标题】:Re-render flat-list in functional component在功能组件中重新渲染平面列表
【发布时间】:2021-01-03 08:44:19
【问题描述】:

我有一个空数组,我将它传递给我的flat-list。 我还使用useEffect 从服务器获取数据并更新列表。 但是,在使用数据设置数组的新状态后,flat-list 不会重新渲染。

const [listData, setlistData] = React.useState<Transaction[]>([])
const [dataUpdated, setDataUpdated] = React.useState<boolean>(false)

React.useEffect(() => {

    if(route.params.showAllData)
    {
        fetchTransactions(1, TRANSACTION_PAGE_SIZE, 1)
            .then((res: Transaction) => {
                console.log(`TransactionsScreen: userEffect [] => fetched ${JSON.stringify(res)}`);
                setlistData(prevState => ({...prevState, ...res}));
                setDataUpdated(true)
            })
            .catch(err => {

                //TODO: handle error scenerio
                ToastAndroid.show(`Failed to fetch transacrions`, ToastAndroid.SHORT)
                
            })
    }}, [])    

<FlatList
     data={listData}
     renderItem={item => _renderItem(item)}
     ItemSeparatorComponent={TransactionListSeparator}
     extraData={dataUpdated} // extraData={listData <--- didn't work either}
     keyExtractor={item => item.id.toString()}/>

我尝试将数据数组添加为 extraData 值,但它不起作用,我还尝试添加另一个布尔值,通知数据已更新,但它也不起作用。

如何正确重新渲染flat-list

【问题讨论】:

  • 您的 useEffect 依赖为空,通过控制台记录检查您的 listData 是否正在更新
  • @GayatriDipali,它确实发生了变化,我在 listData 上还有另一个 useEffect(我没有在此处发布),它记录了更新的值。
  • 你可以尝试传递当前时间状态的密钥吗?

标签: reactjs react-native react-native-flatlist react-typescript


【解决方案1】:

我是这样解决问题的:

useEffect(() => {
    setDataUpdated(!dataUpdated);
  }, [listData]);

注意: 您将 dataUpdated 直接更新为 true。我不建议这样做,而是这样做:setDataUpdated(!dataUpdated)

另外确保FlatList 的所有元素都有一个唯一的键,否则它不会不惜一切代价重新渲染

【讨论】:

  • 我尝试了您的方法并将dataUpdated 添加为extraData,但该列表没有重新渲染.. :/
  • 对不起,我给了一个错误的依赖,现在修复它!
  • 仍然不起作用...我在useEffect中记录了listData,它确实有值。但是我的 _renderItem() 函数永远不会被调用
  • 能不能做个零食放链接
【解决方案2】:

试试这个,确保你返回你的子组件并给依赖数组加上 useEffect 你想重新渲染你的组件的变化

const [listData, setlistData] = React.useState<Transaction[]>([])
const [dataUpdated, setDataUpdated] = React.useState<boolean>(false)

React.useEffect(() => {

    if(route.params.showAllData)
    {
        fetchTransactions(1, TRANSACTION_PAGE_SIZE, 1)
            .then((res: Transaction) => {
                console.log(`TransactionsScreen: userEffect [] => fetched                  ${JSON.stringify(res)}`);
                setlistData(prevState => ({...prevState, ...res}));
                setDataUpdated(true)
            })
            .catch(err => {

                //TODO: handle error scenerio
                ToastAndroid.show(`Failed to fetch transacrions`,                              ToastAndroid.SHORT)
                
            })
    }}, [listData])  
    
    return (

  <FlatList
     data={listData}
     renderItem={item => _renderItem(item)}
     ItemSeparatorComponent={TransactionListSeparator}
     extraData={dataUpdated} // extraData={listData <--- didn't work either}
     keyExtractor={item => item.id.toString()}/>
     
     )

【讨论】:

    【解决方案3】:

    您不能像以前那样扩展数组。例如,如果您有两个数组。

    const arr1 = [1, 2, 3];
    const arr2 = [4, 5, 6];
    

    然后像这样传播它们:

    const arr3 = { ...arr1, ...arr2 };
    

    结果将是:

    { 0: 4, 1: 5, 2: 6 }
    

    将花括号改为正方形。

    setlistData(prevState => ([...prevState, ...res]));
    

    因为您的 FlatList 期望数据是一个数组,而不是一个对象。

    【讨论】:

      【解决方案4】:

      您可以通过将更新后的列表作为 extraData 属性传递来强制平面列表重新呈现,即extraData={listData}。但是,在使用功能组件时,一个常见的错误是传递与 prop 相同的列表数据实例。即使列表中的内容或列表的长度发生了变化,这也不会触发重新渲染。 FlatList 认为这是相同的,不会重新渲染。 要触发重新渲染,您必须创建一个全新的列表实例。

      例如:

      //This update will NOT trigger a rerender
      const copy = listData;
      copy.push(something)
      setListData(copy)
      
      ////////
      <FlatList extraData={listData}
      .....
      />
      
      //This WILL trigger a rerender
      const copy = [...listData]
      copy.push(something)
      setListData(copy)
      
      ////////
      <FlatList extraData={listData}
      .....
      />
      

      【讨论】:

        猜你喜欢
        • 2023-04-03
        • 2017-09-09
        • 2020-10-31
        • 1970-01-01
        • 2020-01-06
        • 2021-12-08
        • 2022-11-29
        • 2021-10-23
        • 2021-03-10
        相关资源
        最近更新 更多