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

时间:2021-01-03 08:44:19

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

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

4 个答案:

答案 0 :(得分:1)

我是这样解决的:

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

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

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

答案 1 :(得分:1)

试试这个,确保你正在返回你的子组件并使用 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()}/>
     
     )

答案 2 :(得分:1)

您不能像以前那样散布阵列。例如,如果您有两个数组。

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

答案 3 :(得分:0)

您可以通过将更新的列表作为 extraData 道具(即 extraData={listData})传递来强制 flatlist 重新呈现。然而,当使用函数式组件时,一个常见的错误是传递与 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}
.....
/>