我有一个由地图渲染的列表组件,这就是我在反应函数组件中定义数据的方式:
const [projMap, setProjMap] = useState<Map<number, FolderModel>>(new Map<number, FolderModel>());
当我在反应功能组件中设置地图时,如下所示:
React.useEffect(() => {
if (folderProjList && folderProjList.length > 0) {
if (currFolder) {
let cachedExpand = projMap.get(currFolder.id)?.expand;
let folderModel: FolderModel = {
expand: cachedExpand ? cachedExpand : true,
projects: folderProjList
};
projMap.set(currFolder.id, folderModel);
setProjMap(projMap);
}
}
}, [folderProjList]);
使用 projMap 渲染 UI 时未触发重新渲染。然后我像这样改变样式:
React.useEffect(() => {
if (folderProjList && folderProjList.length > 0) {
if (currFolder) {
setProjMap((prevMapState) => {
const newMapState = new Map<number, FolderModel>(prevMapState);
let cachedExpand = newMapState.get(currFolder.id)?.expand;
let folderModel: FolderModel = {
expand: cachedExpand ? cachedExpand : true,
projects: folderProjList
};
newMapState.set(currFolder.id, folderModel);
return newMapState;
});
}
}
}, [folderProjList]);
重新渲染效果很好。用户界面始终保持最新。这两种setState有什么不同?为什么第二种风格可以立即重新渲染,而第一种风格却不能?
在第一个中,您要改变映射(通过添加条目),然后将改变的映射设置为状态,因此状态实际上并没有改变(参考),它是相同的映射,只是发生了改变。当状态没有参考改变时,react 不会重新渲染。
在第二个示例中,您将创建一个新地图并将新地图设置为状态,无突变,引用不同。
不要改变状态。
在第一个示例中,您仅改变 Map。Map 是数据的引用类型,这意味着添加或删除某些内容不会触发 React 更新。考虑这个小例子
同时如果你做这样的事情
React 仅进行像上面这样的浅层比较,以了解它是否需要重新渲染。
因此,如果你想更新状态以便 React 重新渲染,你必须创建一个新实例。您的第一个示例也可以像这样重用