为什么更新状态后不响应组件的重新渲染?

时间:2020-07-15 03:36:38

标签: reactjs state rerender

我有一个React应用程序,我需要帮助来重新渲染组件。

该组件代表博客。它列出了从数据库中提取的所有博客。底部有一个表格用于添加新帖子。当我添加新帖子时,我不仅将其发送到后端以保存到数据库中,而且将其添加到前端的博客列表中,以便立即在UI中显示。 <-这是问题。帖子正在添加到处于状态的前端数组中,但是除非刷新页面,否则它不会显示在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);
            });
        }
    }

当我输入控制台日志以查看this.state.blogPosts的内容时,它表明确实添加了新帖子。但是,除非我刷新页面,否则新帖子不会显示在屏幕上。

与我正在调用event.preventDefault()有什么关系吗?

这与我将新帖子添加到状态(this.state.blogPosts)而不是调用setState(...)的数组有关吗?

什至this.forceUpdate()似乎也不起作用。

有人可以看到我在做什么吗?谢谢。

2 个答案:

答案 0 :(得分:3)

这是因为React不知道您的状态正在更新。要通知React,请使用this.setState

this.setState((state) => ({
  blogPosts: [{/*your new blog*/}, ...state.blogPosts]
}));

答案 1 :(得分:0)

深入研究,我发现除了kkesley建议的内容外,问题还在于我对useMemo(...)的使用。为了构造博客文章表,我使用了react-table,其构造是通过在render()中调用createTable()来完成的。该表的数据构建如下:

    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.blogPost传递到react-table组件。

问题在于useMemo始终返回原始dataArray,该数据数组仅包含state.blogPosts中的原始帖子。我将该行更改为将dataArray作为依赖项包括在内:

const data = React.useMemo(() => dataArray, [dataArray]);

这解决了问题。