reactjs 在功能组件中重新渲染平面列表

brvekthn  于 2023-04-29  发布在  React
关注(0)|答案(4)|浏览(165)

我有一个空数组,我传递给我的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

hs1rzwqc

hs1rzwqc1#

您可以通过将更新后的列表作为extraData属性传递来强制flatlist重新呈现。e 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}
.....
/>
lstz6jyr

lstz6jyr2#

我是这样解决这个问题的:

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

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

另外,确保**FlatList的所有元素都有唯一的密钥**,否则不会不惜任何代价重新渲染

ddrv8njm

ddrv8njm3#

试试这个方法,确保你返回了你的子组件,并给出了一个带有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()}/>
     
     )
xmjla07d

xmjla07d4#

你不能像刚才那样展开阵列。例如,如果您有两个数组。

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期望数据是数组,而不是对象。

相关问题