【问题标题】:Show added posts without refreshing page in React在 React 中显示添加的帖子而不刷新页面
【发布时间】:2020-04-22 18:21:34
【问题描述】:

我一直在从事大学以外的个人项目,开发博客。 现在我正在尝试实现一个“主页”,在成功登录后,用户可以发布文本,然后它出现在 Create post div 下,您可以在图片中看到 到目前为止,这是我设法完成的:

This is the home page after login

现在我可以登录并发布一个新帖子,并将其保存在数据库中。

这是用户登录后看到的 home.js 功能组件:

import '../App.css';    
import { useHistory } from "react-router-dom";
import React , {useState, useEffect} from 'react';
import jwt_decode from 'jwt-decode'
import logo from '../images/home-logo.png';
import {Col,Form,Input,Button,Card,CardTitle,Navbar,Nav,NavbarBrand} from 'reactstrap'
import { createPost,getUserPosts } from '../fucntions/user_functions'
function Home(){
    var _decoded;
    var _email;
    let history = useHistory();
    const[post_text,setPost] = useState('');

    const handleChangePost = e =>{ setPost(e.target.value);};


    function handlePost(e){
      e.preventDefault();
      const toPost = {
        post :post_text, email :_email
      }
      createPost(toPost).then(res =>{
        setPost('')
      })
    }

    function getPosts() {
      const container ={
        email:_email
      }
      getUserPosts(container).then(res=>{

      })
    }



    function handleLogout (e) {
        e.preventDefault();
        localStorage.removeItem('usertoken')  
        history.push(`/login`)
    }
    useEffect(() =>{
        if (localStorage.getItem("usertoken") === null) {
            history.push('/login')
        } else {
        const token = localStorage.usertoken
        const user_email = localStorage.useremail
        const decoded = jwt_decode(token)
        _decoded = decoded;
        _email = decoded.email
        getPosts()

    };
});
    return (
      <div className = "box">
        <div>
        <Navbar color="light" light expand="md">
                    <Nav>
                        <NavbarBrand type = "button" onClick = {handleLogout}>Logout</NavbarBrand>
                    </Nav>
        </Navbar>
        <div className = "wrapper">
           <Card body outline color="secondary" className = "card-home " >
            <CardTitle><img src={logo} alt="logo"></img>Create post</CardTitle>
            <Form onSubmit = {handlePost}>
            <Input  id = "tx" name = "input1" type = "textarea" value = {post_text} placeholder="Enter your post here"  onChange= {handleChangePost}></Input>
             <br></br>
            <Col sm={{ span: 10, offset: 5 }}>
              <Button outline color="primary" type="submit">Post!</Button>
            </Col>
            </Form>
           </Card>
          </div>
      </div>

    </div>

    )

}

export default Home;

我在后端实现了一个 getPosts 方法,它返回一个帖子数组

  router.post("/getPosts",
  async (req, res) => {
      const {email,} = req.body;
          try {
              let user = await User.findOne({email:email});
              allPosts = user.posts
             res.render('/home',{posts : hello})
        } catch (e) {
            console.error(e);
            res.json("Error")
      }
    }
);

如上所示,在函数 getPosts() 中,响应是用户发布的所有帖子 id 的数组,它们存储在名为“posts”的 mongodb 集合中 在调用该函数之后,我可以遍历它们:

function getPosts() {
  const container ={
    email:_email
  }
  getUserPosts(container).then(res=>{
    forEach(res.posts) {

    }
  })
}

我想实时渲染所有这些帖子,因此每次用户发布新帖子时,它都会显示在您可以在图片中看到的 Create post div 之后,最好的方法是什么? 谢谢

【问题讨论】:

    标签: node.js reactjs mongodb


    【解决方案1】:

    首先定义你的帖子收藏状态:

    const [allPosts, setAllPosts] = useState([]);
    

    然后每次你成功地在数据库中保存一个帖子时,将它附加到那个状态:​​

    function handlePost(e){
      e.preventDefault();
      const toPost = {
        post :post_text, email :_email
      }
      createPost(toPost).then(res =>{
        setPost('')
        setAllPosts(allPosts.concat(toPost);
      })
    }
    

    getPosts 也是如此:

       function getPosts() {
          const container ={
            email:_email
          }
          getUserPosts(container).then(res=>{
              setAllPosts(res.data); // <-- if the data is the same structure as the created before
          })
        }
    

    然后你可以用一个例子的方式来渲染它们:

    return (
      <div className = "box">
        <div>
          <Navbar color="light" light expand="md">
            <Nav>
              <NavbarBrand type = "button" onClick = {handleLogout}>Logout</NavbarBrand>
            </Nav>
          </Navbar>
          <div className = "wrapper">
            <Card body outline color="secondary" className = "card-home " >
              <CardTitle><img src={logo} alt="logo"></img>Create post</CardTitle>
              <Form onSubmit = {handlePost}>
                <Input  id = "tx" name = "input1" type = "textarea" value = {post_text} placeholder="Enter your post here"  onChange= {handleChangePost}></Input>
                <br></br>
                <Col sm={{ span: 10, offset: 5 }}>
                  <Button outline color="primary" type="submit">Post!</Button>
                </Col>
              </Form>
              <div>
                {
                  allPosts.map(post => {
                    return <div><div>email: {post.email}</div><div>post: post.post</div></div>
                  })
                }
              </div>
            </Card>
          </div>
        </div>
    
      </div>
    
    )
    

    随意更改 HTML 结构,使其与您的设计相匹配

    【讨论】:

    • 谢谢!可以,但是发帖过程很慢(发帖后文字出现很慢),你知道为什么吗?
    • 是的,这是因为您首先将其保存在数据库中,当您收到响应 200(成功)时,您会清除文本。您可以将文本保存在变量中,清除它然后将其发布到服务器,但我不建议这样做,因为如果您的服务器出现故障,您的字段将被清除,这将导致糟糕的用户体验。
    猜你喜欢
    • 2021-11-18
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多