React setState 不重新渲染组件
Posted
技术标签:
【中文标题】React setState 不重新渲染组件【英文标题】:React setState not re-rendering component 【发布时间】:2021-04-28 08:42:48 【问题描述】:我得到以下反应代码
const [folders, setFolders] = useState([
id: 1,
title: 'name',
logo: 'logo',
tasks:
[
id: 1,
text: 'blaas bla bla',
done: true,
,
id: 2,
text: 'bla bla bla',
done: false,
,
]
,
id: 2,
title: 'name',
logo: 'logo',
tasks:
[
id: 3,
text: 'blasdasda bla bla',
done: true,
,
id: 4,
text: 'bla bla bla',
done: false,
,
]
,
id: 3,
title: 'naasdme',
logo: 'logo',
tasks:
[
id: 5,
text: 'bla bla bla',
done: false,
,
id: 6,
text: 'bla bla bla',
done: false,
,
]
]);
function deleteTask( taskId )
setFolders((prev) =>
prev.forEach( (folder) =>
folder.tasks = folder.tasks.filter( task => task.id != taskId )
)
return prev;
);
代码运行良好,它确实更新了状态,但组件不会重新渲染。
我正在使用带有声明式路由的组件,我尝试了几种方法来检查问题是否在路由中,但可能不是。
<Route path='/Tasks/:id' render=(props) =>
(
<Tasks ...props folders=folders onDelete=deleteTask updateTask= updateTask />
)
/>
<Route path='/Tasks/:id' >
<Tasks folders=folders onDelete=deleteTask updateTask=updateTask />
</Route>
<Route path='/Tasks/:id' children=<Tasks folders=folders onDelete=deleteTask
updateTask=updateTask /> />
所有这 3 种方式都可以正常工作。
组件不重新渲染的任何建议方式?
【问题讨论】:
替换 forEach 映射并返回映射数组。 同样的问题改了但是没有重新渲染 【参考方案1】:试试这个:
const deleteTask = (taskId) =>
setFolders((prev) =>
prev.map(( tasks, ...rest ) => (
...rest,
tasks: tasks.filter((task) => task.id !== taskId),
))
);
工作示例:
const App = () =>
const [folders, setFolders] = React.useState([
id: 1,
title: "name",
logo: "logo",
tasks: [
id: 1,
text: "blaas bla bla",
done: true,
,
id: 2,
text: "bla bla bla",
done: false,
,
],
,
id: 2,
title: "name",
logo: "logo",
tasks: [
id: 3,
text: "blasdasda bla bla",
done: true,
,
id: 4,
text: "bla bla bla",
done: false,
,
],
,
id: 3,
title: "naasdme",
logo: "logo",
tasks: [
id: 5,
text: "bla bla bla",
done: false,
,
id: 6,
text: "bla bla bla",
done: false,
,
],
,
]);
const deleteTask = (taskId) =>
setFolders((prev) =>
prev.map(( tasks, ...rest ) => (
...rest,
tasks: tasks.filter((task) => task.id !== taskId),
))
);
return folders.map((folder) => (
<div>
<h1>folder.title</h1>
folder.tasks.map((task) => (
<div>
<p>task.text</p>
<button onClick=() => deleteTask(task.id)>Delete</button>
</div>
))
</div>
));
;
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
【讨论】:
您的解决方案返回任务数组而不是文件夹数组。 错误,可能 setstate 异步。 在您编辑了答案后,它起作用了!谢谢你 没问题,感谢@KirillSkomarovskiy。【参考方案2】:您应该使用map
而不是forEach
,因为 map 返回一个新数组。组件不会重新渲染,因为您修改了数组folders
,但您没有更改引用。 React 不认为状态发生了变化,因为它读取的值(数组«它在内存中的起点»的引用)没有改变。
【讨论】:
同样的问题,它改变了状态,但它没有重新渲染。【参考方案3】:对不起,我是电话打来的。
const deleteTask = (taskId) =>
setFolders((prev) =>
prev.map(( tasks, ...rest ) => ( ...rest, tasks: tasks.filter((task) => task.id !== taskId) )
);
【讨论】:
这是正确答案,我也复制了这个答案。 @b3hr4d 你偷了我的代码并得到正确答案。 ?。以上是关于React setState 不重新渲染组件的主要内容,如果未能解决你的问题,请参考以下文章
React Native this.setState() 仅在再次与组件交互后重新渲染
React 6/100 React原理 | setState | JSX语法转换 | 组件更新机制
React setstate 只能更新挂载或挂载的组件——在重新渲染时