简体   繁体   English

在 React 中显示添加的帖子而不刷新页面

[英]Show added posts without refreshing page in React

I have been working on a personal project outside university, developing a blog.我一直在从事大学以外的个人项目,开发博客。 Right now I'm trying to implement a "home page" where after a succesfull login, the user can post text, and right after that it appears under the Create post div you can see in the pic This is what I have managed to accomplish so far:现在我正在尝试实现一个“主页”,在成功登录后,用户可以发布文本,然后它出现在 Create post div 下,您可以在图片中看到这就是我设法完成的至今:

This is the home page after login这是登录后的首页

Right now I can login, and post a new post which saves it in the database.现在我可以登录并发布一个新帖子,将其保存在数据库中。

This is the home.js functional componenet which the user sees after a 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;

I have implemented a getPosts method in the backend which gives back an array of the posts我在后端实现了一个 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")
      }
    }
);

As you can see above, in the function getPosts(), the response is an Array of all the post's ids the user has posted, they are stored in the mongodb collection called "posts" And after calling that function, I can iterate over them: As you can see above, in the function getPosts(), the response is an Array of all the post's ids the user has posted, they are stored in the mongodb collection called "posts" And after calling that function, I can iterate over them :

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

    }
  })
}

I want to render all those posts live, so each time the user posts a new post, it will show right after the Create post div you can see in the picture, What's the best way?我想实时渲染所有这些帖子,所以每次用户发布新帖子时,它都会显示在您可以在图片中看到的 Create post div 之后,最好的方法是什么? Thanks谢谢

First define your posts collection state:首先定义您的帖子集合 state:

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

Then every time you successfully save a post in the database, append it to that state:然后每次你在数据库中成功保存一个帖子,append 它到那个 state:

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

The same goes for getPosts: 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
      })
    }

Then you can render them in an example way:然后您可以以示例方式呈现它们:

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>

)

Feel free to change the HTML structure, so it matches your design随意更改 HTML 结构,使其符合您的设计

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM