gpt4 book ai didi

reactjs - 防止重新渲染 flatlist React Native

转载 作者:行者123 更新时间:2023-12-05 04:31:42 30 4
gpt4 key购买 nike

我使用 Flatlist 自定义创建了日历。在父组件中,我有一个具有开始日期和结束日期的状态,以及当用户按下日期时按下处理程序函数来更新状态。问题是每次我按下日期渲染函数时都会调用。

问题是:如何保持状态变化,而不是一次又一次地重新渲染整个日历?

带有 FlatList 的父组件。

interface Props {
arrivalDate: string | undefined;
departureDate: string | undefined;
onDayPress: (day: Date) => void;
futureYearRange?: number;
}

const CustomCalendarList: React.FC<Props> = ({
arrivalDate,
departureDate,
futureYearRange = 5,
onDayPress,
}) => {
const months = useMonths();
const [isLoading, setIsLoading] = useState(true);
const [dates, setDates] = useState({
endDate: arrivalDate,
startDate: departureDate,
});

const handleDayPress= useCallback((row:IRow) => (e?: GestureResponderEvent) => {
if (!dates.startDate || (dates.startDate && dates.endDate)) {
setDates({endDate: undefined, startDate: row.date});
} else {
setDates(prevState => ({...prevState, endDate: row.date}))
}
}, [setDates]);

const { grids, monthsToRender } = useMemo(() => {
const monthToRender = 11 - dayjs().month() + futureYearRange;
const monthsToRender: Array<{ title: string; year: number }> = [];
const grids = [];

for (let i = 0; i < monthToRender; i++) {
const newGrid: Array<Array<IRow>> = [];
const date = dayjs().add(i, "month");
const daysInMonth = dayjs(date).daysInMonth();
const monthIndex = dayjs(date).month();
const year = dayjs(date).year();
monthsToRender.push({ title: months[monthIndex], year });

for (let j = 0; j < daysInMonth - 1; j++) {
let row = [];
// minus 1 because by default in dayjs start week day is sunday(index=0)
let startingIndex = j === 0 ? dayjs(date).startOf("month").day() - 1 : 0;
startingIndex = startingIndex === -1 ? 6 : startingIndex;

for (let k = startingIndex; k < 7; k++) {
if (!(j + 1 > daysInMonth)) {
row[k] = {
day: j + 1,
date: dayjs(date)
.date(j + 1)
.format("YYYY-MM-DD"),
};
}
if (k === 6) {
newGrid.push(row);
} else {
j += 1;
}
}
}
grids.push(newGrid);
};
console.log('generated')
return {
grids,
monthsToRender
};
}, [futureYearRange]);


const renderItem = useCallback(({
item,
index,
}: ListRenderItemInfo<Array<Array<IRow>>>) => {
return (
<Grid
onPress={handleDayPress}
monthsToRender={monthsToRender}
grid={item}
gridIndex={index}
/>
);
}, [dates.startDate, dates.endDate]);

useEffect(() => {
const timeoutId = setTimeout(() => {
setIsLoading(false);
}, 300);
return () => {
clearTimeout(timeoutId);
};
}, []);

if (isLoading) {
return (
<View
style={css`
height: 90%;
justify-content: center;
align-items: center;
background: ${colors.primaryBg};
`}
>
<ActivityIndicator color={"blue"} size="large" />
</View>
);
}

return (
<Calendar>
<FlatList
data={grids}
showsVerticalScrollIndicator={false}
updateCellsBatchingPeriod={1000}
renderItem={renderItem}
maxToRenderPerBatch={3}
keyExtractor={() => uuidv4()}
/>
</Calendar>
);
};

enter image description here

最佳答案

问题

每次组件呈现时,您都会生成新的 React 键。

<FlatList 
data={grids}
showsVerticalScrollIndicator={false}
updateCellsBatchingPeriod={1000}
renderItem={renderItem}
maxToRenderPerBatch={3}
keyExtractor={() => uuidv4()} // <-- new React key each render cycle!
/>

对于不稳定的键,React 假定这些都是新元素,需要挂载和渲染。使用数组索引会是一个更好的解决方案(不要那样做!!)。

解决方案

将生成的 GUID 添加为属性,然后可以在渲染时提取该属性。

例子:

const { grids, monthsToRender } = useMemo(() => {
...
const grids = [];

for (let i = 0; i < monthToRender; i++) {
...

for (let j = 0; j < daysInMonth - 1; j++) {
...

for (let k = startingIndex; k < 7; k++) {
if (!(j + 1 > daysInMonth)) {
row[k] = {
guid: uuidV4(), // <-- generate here
day: j + 1,
date: dayjs(date)
.date(j + 1)
.format("YYYY-MM-DD")
};
}
if (k === 6) {
newGrid.push(row);
} else {
j += 1;
}
}
}
grids.push(newGrid);
}

return {
grids,
monthsToRender
};
}, [futureYearRange]);

...

<FlatList 
data={grids}
showsVerticalScrollIndicator={false}
updateCellsBatchingPeriod={1000}
renderItem={renderItem}
maxToRenderPerBatch={3}
keyExtractor={({ guid }) => guid} // <-- extract here
/>

关于reactjs - 防止重新渲染 flatlist React Native,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71800655/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com