react-native - React Native List 项目记忆
问题描述
我试图防止FlatList
使用不必要的物品渲染,React.memo()
但我遇到了一些奇怪的行为。提供前一个 props 和下一个 props 的回调总是具有相同的值,即使它们在链的上层发生了变化。
export default React.memo(PersonCell, (prev, next) => {
reactotron.log(`prev ${prev.person.name}: is checked${prev.person.isChecked}`)
reactotron.log(`next ${next.person.name}: is checked${next.person.isChecked}`)
return prev.person.isChecked === next.person.isChecked
})
我拥有的链是我使用Realm
的一个非常简单的结构,{id:number, name:string, isChecked:boolean}
每当他们点击单元格时,它都会写入领域,在应用程序的顶层,我有一个数据更改的侦听器,然后设置状态以将其传播回名单
let [data, setData] = useState([]);
useEffect(() => {
let sub = person$.subscribe({
next: collection => {
reactotron.logImportant!(collection)
setData([...data, ...collection.map(x => x)]);
},
});
这是单元格代码
import React from 'react';
import { Subject } from "rxjs";
import { useEffect } from "react";
import realm, { PersonSchema } from "./realm";
import { Person } from "./PersonsList";
import { View, TouchableOpacity, Text } from "react-native";
import reactotron from 'reactotron-react-native';
interface Props {
person: Person
}
const onCheck$ = new Subject<number>();
const PersonCell: React.FC<Props> = props => {
useEffect(() => {
let sub = onCheck$.subscribe({
next: x => {
realm.write(() => {
let person = realm.objectForPrimaryKey<Person>(PersonSchema.name, x);
if (!person) return;
person.isChecked = !person.isChecked;
});
},
});
return () => sub.unsubscribe;
}, []);
return (
<View>
<Text>{props.person.name}</Text>
<TouchableOpacity onPress={() => onCheck$.next(props.person.id)}>
<View
style={{
backgroundColor: props.person.isChecked
? 'rgb(255,1,1)'
: 'rgb(1,1,255)',
width: 20,
height: 20,
}}
/>
</TouchableOpacity>
</View>
);
};
PersonCell.whyDidYouRender = true;
// export default React.memo(PersonCell)
export default React.memo(PersonCell, (prev, next) => {
reactotron.log(`prev ${prev.person.name}: is checked${prev.person.isChecked}`)
reactotron.log(`next ${next.person.name}: is checked${next.person.isChecked}`)
return prev.person.isChecked === next.person.isChecked
})
这是预期的行为还是我做错了什么? 这是我正在解释的回购
更新
我删除了平面列表并使用基本地图和密钥来生成项目列表,当前道具仍然出现上述问题,shouldComponentUpdate
并且React.memo
第二个参数中传入的道具仍然完全相同,尽管已更改。
这是一个经历类似事情的人的链接
解决方案
我相信这个问题是由于以非反应方式改变状态。我相信这个
let sub = person$.subscribe({
next: collection => {
setData(collection.map(x => x));
},
});
返回一个新数组就足够了(因为 map 返回一个全新的数组)以使用所需的更改比较来更新状态。但显然您需要执行以下操作。
let sub = person$.subscribe({
next: collection => {
setData(collection.map(x => x).map(x => _.toPlainObject(x)));
},
});
即对从领域返回的每个对象进行深度克隆,以使其正常工作......或者打字稿可能存在问题。
如果有人想提供更简洁的答案,我们非常欢迎。
无论哪种方式,如果有人想查看它,repo 已经更新了更改。
推荐阅读
- clips - clipspy 安装致命错误 C1083:无法打开包含文件:'clips.h':没有这样的文件或目录
- node.js - 在 e2e 测试运行后,Bash 脚本卡住了
- sql-server - 如何在 SQL Server 中屏蔽特定用户
- azure - 尽管订阅者有正确的产品订阅密钥,但 Azure APIM 网关反复显示“401 Unauthorized”。HTTP 试用请求失败
- typo3 - 自定义 TYPO3 扩展的 RouteEnhancer:详细信息页面上的 404
- algorithm - 对于矩阵中的零元素,如何探索具有最大可能连续长度的相邻区域?
- javascript - 在 Markdown-it 中渲染令牌?
- windows - windows redis-client 连接到 docker 服务器失败
- python - 如何在 Python 中绘制具有缺失值的组条
- awk - 用列表中的数字替换模板文件中的数字并输出到不同的文件