为什么更新状态时不会反应组件重新渲染?
Why won't react component rerender when state is updated?
我有一个 React 应用程序,我需要帮助让组件重新呈现。
该组件代表一个博客。它列出了从数据库中提取的所有博客。底部有一个用于添加新 post 的表格。当我添加一个新的 post 时,我不仅将它发送到后端以保存到数据库中,而且我将它添加到前端的博客列表中,以便它立即显示在 UI. <-- 这就是问题所在。 post 正在添加到处于状态的前端数组,但它不会显示在 UI 中,除非我刷新页面。
这是我的代码:
submitHandler(event) {
event.preventDefault();
let formData = new FormData();
formData.append('title', this.postTitleRef.current.value);
formData.append('body', this.postBodyRef.current.value);
if (this.state.file) {
formData.append('image', this.state.file);
}
if (this.state.editPostId) {
formData.append('postId', this.state.editPostId);
const editPost = this.state.blogPosts.find(p => p.id === this.state.editPostId);
if (editPost.filename) {
formData.append('filename', editPost.filename);
}
axios.patch('/blogs', formData, {
headers: {
Authorization: this.state.accessToken,
'content-type': 'multipart/form-data'
}
}).then(response => {
const existingPost = this.state.blogPosts.find(p => p.id === this.state.editPostId);
existingPost.title = this.postTitleRef.current.value;
existingPost.body = this.postBodyRef.current.value;
existingPost.updatedAt = response.data.updatedAt;
existingPost.filename = response.data.filename || existingPost.filename;
existingPost.imageUrl = response.data.imageUrl || existingPost.imageUrl;
this.state.blogPosts.sort((p1, p2) => p1.updatedAt > p2.updatedAt ? -1 : 1);
this.clearForm();
}).catch(err => {
console.log('err=', err);
});
} else {
axios.post('/blogs', formData, {
headers: {
Authorization: this.state.accessToken,
'content-type': 'multipart/form-data'
}
}).then(response => {
this.state.blogPosts.unshift({
id: response.data.id,
createdAt: response.data.createdAt,
updatedAt: response.data.createdAt,
filename: response.data.filename || null,
title: this.postTitleRef.current.value,
body: this.postBodyRef.current.value,
imageUrl: response.data.imageUrl || null
});
this.clearForm();
}).catch(err => {
console.log('err=', err);
});
}
}
当我把console登录进去看到this.state.blogPosts的内容时,显示确实添加了新的post。但是新的 post 不会出现在屏幕上,除非我刷新页面。
这与我调用 event.preventDefault() 有什么关系吗?
这与我将新的 post 添加到状态 (this.state.blogPosts) 中的数组而不是调用 setState(...) 有什么关系吗?
甚至 this.forceUpdate() 似乎都不起作用。
谁能看出我做错了什么?谢谢
这是因为 React 不知道您的状态正在更新。要让 React 知道,请使用 this.setState
this.setState((state) => ({
blogPosts: [{/*your new blog*/}, ...state.blogPosts]
}));
深入挖掘,我发现除了 kkesley 的建议之外,问题还在于我对 useMemo(...) 的使用。为了构造博客文章的 table,我使用了 react-table,其构造是通过调用 render() 中的 createTable() 完成的。 table 的数据构建如下:
for (var index = 0; index < props.posts.length; index++) {
const post = props.posts[index];
dataArray.push({
titleCol: post.title,
bodyCol: post.body,
updatedAtCol: post.updatedAt,
imageUrlCol: post.imageUrl[0]
});
}
const data = React.useMemo(() => dataArray, []);
...其中 props.posts 是 state.blogPosts 传递给 react-table 组件。
问题是 useMemo 总是返回原始的 dataArray,它只包含 state.blogPosts 中的原始帖子。我更改了该行以将 dataArray 作为依赖项包括在内:
const data = React.useMemo(() => dataArray, [dataArray]);
这解决了问题。
我有一个 React 应用程序,我需要帮助让组件重新呈现。
该组件代表一个博客。它列出了从数据库中提取的所有博客。底部有一个用于添加新 post 的表格。当我添加一个新的 post 时,我不仅将它发送到后端以保存到数据库中,而且我将它添加到前端的博客列表中,以便它立即显示在 UI. <-- 这就是问题所在。 post 正在添加到处于状态的前端数组,但它不会显示在 UI 中,除非我刷新页面。
这是我的代码:
submitHandler(event) {
event.preventDefault();
let formData = new FormData();
formData.append('title', this.postTitleRef.current.value);
formData.append('body', this.postBodyRef.current.value);
if (this.state.file) {
formData.append('image', this.state.file);
}
if (this.state.editPostId) {
formData.append('postId', this.state.editPostId);
const editPost = this.state.blogPosts.find(p => p.id === this.state.editPostId);
if (editPost.filename) {
formData.append('filename', editPost.filename);
}
axios.patch('/blogs', formData, {
headers: {
Authorization: this.state.accessToken,
'content-type': 'multipart/form-data'
}
}).then(response => {
const existingPost = this.state.blogPosts.find(p => p.id === this.state.editPostId);
existingPost.title = this.postTitleRef.current.value;
existingPost.body = this.postBodyRef.current.value;
existingPost.updatedAt = response.data.updatedAt;
existingPost.filename = response.data.filename || existingPost.filename;
existingPost.imageUrl = response.data.imageUrl || existingPost.imageUrl;
this.state.blogPosts.sort((p1, p2) => p1.updatedAt > p2.updatedAt ? -1 : 1);
this.clearForm();
}).catch(err => {
console.log('err=', err);
});
} else {
axios.post('/blogs', formData, {
headers: {
Authorization: this.state.accessToken,
'content-type': 'multipart/form-data'
}
}).then(response => {
this.state.blogPosts.unshift({
id: response.data.id,
createdAt: response.data.createdAt,
updatedAt: response.data.createdAt,
filename: response.data.filename || null,
title: this.postTitleRef.current.value,
body: this.postBodyRef.current.value,
imageUrl: response.data.imageUrl || null
});
this.clearForm();
}).catch(err => {
console.log('err=', err);
});
}
}
当我把console登录进去看到this.state.blogPosts的内容时,显示确实添加了新的post。但是新的 post 不会出现在屏幕上,除非我刷新页面。
这与我调用 event.preventDefault() 有什么关系吗?
这与我将新的 post 添加到状态 (this.state.blogPosts) 中的数组而不是调用 setState(...) 有什么关系吗?
甚至 this.forceUpdate() 似乎都不起作用。
谁能看出我做错了什么?谢谢
这是因为 React 不知道您的状态正在更新。要让 React 知道,请使用 this.setState
this.setState((state) => ({
blogPosts: [{/*your new blog*/}, ...state.blogPosts]
}));
深入挖掘,我发现除了 kkesley 的建议之外,问题还在于我对 useMemo(...) 的使用。为了构造博客文章的 table,我使用了 react-table,其构造是通过调用 render() 中的 createTable() 完成的。 table 的数据构建如下:
for (var index = 0; index < props.posts.length; index++) {
const post = props.posts[index];
dataArray.push({
titleCol: post.title,
bodyCol: post.body,
updatedAtCol: post.updatedAt,
imageUrlCol: post.imageUrl[0]
});
}
const data = React.useMemo(() => dataArray, []);
...其中 props.posts 是 state.blogPosts 传递给 react-table 组件。
问题是 useMemo 总是返回原始的 dataArray,它只包含 state.blogPosts 中的原始帖子。我更改了该行以将 dataArray 作为依赖项包括在内:
const data = React.useMemo(() => dataArray, [dataArray]);
这解决了问题。