首页 > 解决方案 > 页面刷新后内容消失

问题描述

我的反应应用程序有问题。我有一个博客页面,我可以在其中创建博客文章并将它们显示到屏幕上。在这部分,一切正常。用户登录并可以写帖子。每篇文章都包含一个阅读更多...链接,如果用户单击该链接,应用程序将重定向到实际的博客文章。在那里,用户可以阅读整个博客并添加一些评论。一切正常,除了当用户刷新页面时,一切都消失了,控制台中没有任何错误。我使用 firebase 作为我的后端,一切都保存在那里,就像它必须保存的那样。每次单击特定帖子时,我都会被重定向到该帖子,一切正常,但是当我刷新页面时,所有内容都消失了,帖子,评论,甚至输入字段和提交评论按钮都消失了。

这是刷新前的图片: 之前

这是刷新后的图片: 之后

我还将包括实际博客和评论部分的代码。BlogAndCommentPage 包含实际的博客文章,并保存评论的输入字段和属于该文章的评论。

import React from 'react'
import { projectFirestore } from '../../firebase/config';
import BackToBlogs from './BackToBlogs'
import AddComment from '../commentComponents/AddComment'

class BlogAndCommentPage extends React.Component {
    state = { param: '', blog: [] }

    componentDidMount = () => {
        const queryString = window.location.search;
        const urlParams = new URLSearchParams(queryString)
        const id = urlParams.get('id')
        this.setState({ param: id })

        const fetchDataFromFireBase = async () => {
            projectFirestore.collection('Blogs').doc(id).get()
                .then(doc => {
                    if(doc.exists) {
                        let document = [];
                        document.push(doc.data());
                        this.setState({ blog: document })
                    }
                })
        }

        fetchDataFromFireBase()
    }
    
    renderContent() {
        // Display the blog
        const blogs = this.state.blog?.map(value => {
            return (
                <div key={value.post.blogID}>
                    <h1>{value.post.title}</h1>
                    <h6>{`${value.post.name} - ${value.post.date}`}</h6>
                    <p>{value.post.body}</p>
                </div>
            )
        })
        return blogs;
    }

    render() {
        const displayedBlog = this.state.param
        return (
            <div>
                {
                    displayedBlog ? (
                        <div>
                        {this.renderContent()}
                        <BackToBlogs />
                        <hr></hr>
                        <h5 className="mb-2">Add a comment</h5>
                        <AddComment param={this.state.param} />
                        </div>
                    ) : ''
                }
            </div>
        )
    }
}

export default BlogAndCommentPage

AddComment 组件包含评论的提交按钮和组件列表

import React, { useState, useEffect } from 'react'
import SubmitComment from './SubmitComment'
import CommentHolder from './CommentHolder';
import { useSelector, useDispatch } from 'react-redux';

const AddComment = ({ param }) => {
    const [comment, setComment] = useState('');

    useEffect(() => {
        if (sessionStorage.getItem('user') === null) {
            alert('You are not logged in. Click OK to log in.')
            window.location = 'http://localhost:3000/'
        }
    }, [])

    const dispatch = useDispatch();
    const state = useSelector((state) => state.state);

    if (state) {
        setTimeout(() => {
            setComment('')
            dispatch({ type: "SET_FALSE" })
        }, 50)
    }

    return (
        <div>
            <div>
                <div className="row">
                    <div className="col-sm">
                        <div className="form-group">
                            <textarea rows="4" cols="50" placeholder="Comment" className="form-control mb-3" value={comment} onChange={(e) => setComment(e.target.value)} />
                        </div>
                    </div>
                </div>
            </div>
            <div className="mb-3">
                <SubmitComment comment={comment} param={param} />
            </div>
            <CommentHolder param={param} />
        </div>
    )
}

export default AddComment

CommentHolder 呈现属于该帖子的每个评论

import React from 'react';
import { projectFirestore } from '../../firebase/config';
import DeleteComment from './DeleteComment'

class CommentHolder extends React.Component {

    state = { docs: [] }
    _isMounted = false;

    componentDidMount = () => {
        const fetchDataFromFireBase = async () => {
            const getData = await projectFirestore.collection("Comments")
            getData.onSnapshot((querySnapshot) => {
                var documents = [];
                querySnapshot.forEach((doc) => {
                    documents.push({ ...doc.data(), id: doc.id });
                });
                if (this._isMounted) {
                    this.setState({ docs: documents })
                }
            });
        }
        fetchDataFromFireBase()
        this._isMounted = true;
    }

    componentWillUnmount = () => {
        this._isMounted = false;
    }

    renderContent() {

        // Delete comments
        const deleteComment = async (id) => {
            projectFirestore.collection('Comments').doc(String(id)).delete().then(() => {
                console.log(`Blog with id: ${id} has been successfully deleted!`)
            })
        }

        // Build comments
        let user;
        if (sessionStorage.getItem('user') === null) {
            user = [];
        } else {
            user = JSON.parse(sessionStorage.getItem('user'));

            const commentArray = this.state.docs?.filter(value => value.blogID === this.props.param)
                .sort((a, b) => (a.time > b.time) ? -1 : (b.time > a.time) ? 1 : 0)
                    .map(comment => {
                return (
                    <div key={comment.id} className="card mb-3" >
                        <div className="card-body">
                            <div className="row">
                                <div className="col-sm">
                                    <h6>{`${comment.name} - ${comment.time}`}</h6>
                                    <p>{comment.comment}</p>
                                </div>
                                <div className="col-sm text-right">
                                    {user[0].id === comment.userID ? <DeleteComment commentid={comment.id} onDeleteComment={deleteComment} /> : ''}
                                </div>
                            </div>
                        </div>
                    </div>
                )
            });

            const updateComments = () => {
                const queryString = window.location.search;
                const urlParams = new URLSearchParams(queryString)
                const id = urlParams.get('id')

                const updateComment = projectFirestore.collection('Blogs').doc(id);
                return updateComment.update({
                    'post.comments': commentArray.length
                })
            }
            updateComments()
            return commentArray;

        }
    }

    render() {
        return (
            <div>
                {this.renderContent()}
            </div>
        )
    }
}

export default CommentHolder

DeleteComment 删除评论

import React from 'react'

const DeleteComment = ({ commentid, onDeleteComment }) => {

    return (
        <div>
            <button onClick={() => onDeleteComment(commentid)} className='btn btn-outline-danger'>X</button>
        </div>
    )
}

export default DeleteComment

SubmitComment 将评论存储在 Firebase 中

import React from 'react'
import { projectFirestore } from '../../firebase/config';
import { v4 as uuidv4 } from 'uuid';
import { useDispatch } from 'react-redux';

const SubmitComment = ({ comment, param }) => {

    const dispatch = useDispatch();

    const onCommentSubmit = () => {
        let user;
        if (sessionStorage.getItem('user') === null) {
            user = [];
        } else {
            user = JSON.parse(sessionStorage.getItem('user'));
            projectFirestore.collection('Comments').doc().set({
                id: uuidv4(),
                comment,
                name: `${user[0].firstName} ${user[0].lastName}`,
                userID: user[0].id,
                blogID: param,
                time: new Date().toLocaleString()
            })

            dispatch({ type: "SET_TRUE" });
        }
    }

    

    return (
        <div>
            <button onClick={() => onCommentSubmit()} className='btn btn-primary'>Add comment</button>
        </div>
    )
}

export default SubmitComment

如果出现路由问题,这里是 blogs 部分和 blog + comments 部分之间路由的代码

    return (
        <Router >
            <Route path='/content-page' exact render={(props) => (
                <>
                    <BlogAndCommentPage />
                </>
            )} />
            <Route path='/blogpage' exact render={(props) => (
                <>
                    <div>
                        <div className="row">
                            <div className="col-8">
                                <h1 className='mb-3'>Blog</h1>
                            </div>
                            <div className="col-4 mb-3">
                                <LogoutButton onLogOut={logout} />
                                <h6 className='float-right mt-4 mr-2'>{displayUser}</h6>
                            </div>
                        </div>
                        {empty ? (<div style={{ color: "red", backgroundColor: "#F39189", borderColor: "red", borderStyle: "solid", borderRadius: "5px", textAlign: 'center' }} className="mb-2">Title and body cannot be blank</div>
                        ) : ("")}
                        <InputArea getBlogContent={getBlogContent} />
                        <CreateBlog post={post} onCheckEmptyInputs={checkEmptyTitleAndBody} />
                        <hr />
                        <BlogHolder />
                    </div>
                </>
            )} />

        </Router>

    )

如果有人对为什么会发生这种情况有任何线索,请告诉我。谢谢你。

标签: reactjs

解决方案


由于您的网站是 CSR(客户端渲染),它在第一次执行时不理解 URL,您可能需要配置一个哈希路由器,看看:

https://reactrouter.com/web/api/HashRouter

此外,这里有一个很好的答案


推荐阅读