简体   繁体   English

使用 useState 时前端不更新

[英]Frontend not updating when using useState

So I have this blog application where I have to sort the blogs depending on the number of likes it has.所以我有这个博客应用程序,我必须根据喜欢的数量对博客进行排序。 This works fine when I first log in the app to see the blogs and also whenever I refresh the page.当我第一次登录应用程序查看博客时,以及每当我刷新页面时,这都很好用。 More specifically, when I first log into the app and when I refresh the page everything is/gets sorted.更具体地说,当我第一次登录应用程序并刷新页面时,所有内容都已排序。 Is there anyway to update/sort the blog list on the fronted without refreshing the page?有没有办法在不刷新页面的情况下更新/排序前面的博客列表?

import { useState, useEffect } from 'react'
import Blog from './components/Blog'
import Login from './components/Login'
import CreateBlog from './components/CreateBlog'
import blogService from './services/blogs'
import loginService from './services/login'
import './app.css';

const App = () => {
  const [blogs, setBlogs] = useState([]) // Unsorted array
  const [user, setUser] = useState(null)
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const [errorMsg, setErrorMsg] = useState('')
  const [msg, setMsg] = useState('')
  const [sortedArray, setSortedArray] = useState(null) //This sorts the original blog array

  const [visibility, setVisibility] = useState(false)


  useEffect( () => {
    if(user != null){
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
    }
    console.log("blogs is", blogs)
  }, [user,sortedArray])

  useEffect(() => {
    const loggedInUser = window.localStorage.getItem('loggedBlogUser')
    console.log("loggedInUser is", loggedInUser)
    if(loggedInUser){
      const user = JSON.parse(loggedInUser)
      blogService.setToken(user.token)
      console.log("user is", user)
      setUser(user)
    }
    else{
      console.log("Error here,", JSON.parse(loggedInUser))
    }
  },[])


  const handleLogin = async (event) => {
    event.preventDefault()
    console.log("Logging in,", username, password)
    try {
      const user = await loginService({username, password})
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
      blogService.setToken(user.token)
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))
      setUser(user)
      setUsername('')
      setPassword('')
    }
    catch(error){
      setErrorMsg('Wrong username or password')
      setTimeout(() => {
        setErrorMsg('')
      },3000)
    }
  }

  const handleLogout = () => {
    window.localStorage.removeItem('loggedBlogUser')
    setUser(null)
    setBlogs([])
    setSortedArray([])

  }

  const addNewBlog = async (blogObject) => {
    try {
      const result = await blogService.createBlog(blogObject)
      const result2 = await blogService.getUserBlogs(result.blog.slice(-1)[0])
      user.blog = user.blog.concat(result2)
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
      console.log("USER USER USER IS", user)
      setVisibility(false)
      setMsg(`a new blog ${blogObject.title} by ${user.name} added`)
      setTimeout(() => {
        setMsg('')
      },3000)
    }
    catch(error){
      console.log("error adding new blog", error)
    }
  }

  return (
    <div>
      <h2>blogs</h2>
      {msg !== '' && <h1 className='successMsg-container'>{msg}</h1>}
      {errorMsg !== '' && <h1 className='errorMsg-container'>{errorMsg}</h1>}
      {user == null && 
      <Login
        handleLogin={handleLogin}
        setUsername={setUsername}
        setPassword={setPassword}
        username={username}
        password={password}>
      </Login>
      }
      {user != null && <div className="notes">
        <p>{user.name} logged in <button onClick={handleLogout}>logout</button></p>
      </div>}
      {user != null && 
      <CreateBlog
        addNewBlog={addNewBlog}
        visibility={visibility} 
        setVisibility={setVisibility}>
      </CreateBlog>
      }
      {sortedArray !== null && sortedArray.map(blog =>
        <Blog key={blog.id} blog={blog} setBlogs={setBlogs} setSortedArray={setSortedArray} user={user} />
      )}
    </div>
  )
}

export default App

Blog code博客代码

import blogService from "../services/blogs"

const Blog = ({blog,user,setBlogs,setSortedArray}) => {
  const [view, setView] = useState(false)
  const [likeCount, setLikeCount] = useState(0)
  

  const hideWhenVisible = {display: view ? 'none' : ''}
  const showWhenVisible = {display: view ? '': 'none'}

  const handleLikeClick = async (blog) => {
    const id = blog.id
    const actualBlog = await blogService.getUserBlogs(id)

    try {
      const updatedBlog = {
        user: [blog.user[0]],
        likes: actualBlog.likes + 1,
        author: blog.author,
        id: actualBlog.id,
        title: blog.title,
        url: blog.url
      }
      setLikeCount(updatedBlog.likes)

      var elementPos = user.blog.map(ranBlog => {return ranBlog.id}).indexOf(blog.id)
      user.blog[elementPos] = updatedBlog
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))

      const result = await blogService.updateBlog(updatedBlog,id)

    }
    catch(error){
      console.log("error liking blog")
    }
  }

  return ( 
    <div className="blog-container">
        {blog.title}  
        <button onClick={() => setView(true)} style={hideWhenVisible}>view</button>
        <button onClick={() => setView(false)} style={showWhenVisible}>hide</button>
          {view && <div className="expanded-view-container">
            <li className="extra-blog-info">
              <ul>{blog.url}</ul>
            {likeCount === 0 && <ul>likes: {blog.likes} <button onClick={() => handleLikeClick(blog)}>like</button></ul>}
            {likeCount !== 0 && <ul>likes: {likeCount} <button onClick={() => handleLikeClick(blog)}>like</button></ul>}
              <ul>{blog.author}</ul>
              <ul>{blog.id}</ul>
            </li>
          </div>}
    </div> 
   );
}
 
export default Blog;

From your code of Blog component, I have seen that you haven't called setBlogs and setSortedArray which update blog states from App .从您的Blog组件代码中,我看到您没有调用setBlogssetSortedArrayApp更新博客状态。

I'd propose you should have another callback function called afterLikeClicked in Blog to update blogs state which will make UI re-rendered.我建议你应该有另一个回调 function 在Blog中调用afterLikeClicked来更新blogs state 这将使 UI 重新呈现。

import blogService from "../services/blogs"

const Blog = ({blog, user, afterLikeClicked}) => {
  const [view, setView] = useState(false)
  const [likeCount, setLikeCount] = useState(0)
  

  const hideWhenVisible = {display: view ? 'none' : ''}
  const showWhenVisible = {display: view ? '': 'none'}

  const handleLikeClick = async (blog) => {
    const id = blog.id
    const actualBlog = await blogService.getUserBlogs(id)

    try {
      const updatedBlog = {
        user: [blog.user[0]],
        likes: actualBlog.likes + 1,
        author: blog.author,
        id: actualBlog.id,
        title: blog.title,
        url: blog.url
      }
      setLikeCount(updatedBlog.likes)
      
      //The change is here
      afterLikeClicked(updatedBlog)

      var elementPos = user.blog.map(ranBlog => {return ranBlog.id}).indexOf(blog.id)
      user.blog[elementPos] = updatedBlog
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))

      const result = await blogService.updateBlog(updatedBlog,id)

    }
    catch(error){
      console.log("error liking blog")
    }
  }

  return ( 
    <div className="blog-container">
        {blog.title}  
        <button onClick={() => setView(true)} style={hideWhenVisible}>view</button>
        <button onClick={() => setView(false)} style={showWhenVisible}>hide</button>
          {view && <div className="expanded-view-container">
            <li className="extra-blog-info">
              <ul>{blog.url}</ul>
            {likeCount === 0 && <ul>likes: {blog.likes} <button onClick={() => handleLikeClick(blog)}>like</button></ul>}
            {likeCount !== 0 && <ul>likes: {likeCount} <button onClick={() => handleLikeClick(blog)}>like</button></ul>}
              <ul>{blog.author}</ul>
              <ul>{blog.id}</ul>
            </li>
          </div>}
    </div> 
   );
}
 
export default Blog;

And then update App accordingly然后相应地更新App

import { useState, useEffect } from 'react'
import Blog from './components/Blog'
import Login from './components/Login'
import CreateBlog from './components/CreateBlog'
import blogService from './services/blogs'
import loginService from './services/login'
import './app.css';

const App = () => {
  const [blogs, setBlogs] = useState([]) // Unsorted array
  const [user, setUser] = useState(null)
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const [errorMsg, setErrorMsg] = useState('')
  const [msg, setMsg] = useState('')
  const [sortedArray, setSortedArray] = useState(null) //This sorts the original blog array

  const [visibility, setVisibility] = useState(false)


  useEffect( () => {
    if(user != null){
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
    }
    console.log("blogs is", blogs)
  }, [user,sortedArray])

  useEffect(() => {
    const loggedInUser = window.localStorage.getItem('loggedBlogUser')
    console.log("loggedInUser is", loggedInUser)
    if(loggedInUser){
      const user = JSON.parse(loggedInUser)
      blogService.setToken(user.token)
      console.log("user is", user)
      setUser(user)
    }
    else{
      console.log("Error here,", JSON.parse(loggedInUser))
    }
  },[])


  const handleLogin = async (event) => {
    event.preventDefault()
    console.log("Logging in,", username, password)
    try {
      const user = await loginService({username, password})
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
      blogService.setToken(user.token)
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))
      setUser(user)
      setUsername('')
      setPassword('')
    }
    catch(error){
      setErrorMsg('Wrong username or password')
      setTimeout(() => {
        setErrorMsg('')
      },3000)
    }
  }

  const handleLogout = () => {
    window.localStorage.removeItem('loggedBlogUser')
    setUser(null)
    setBlogs([])
    setSortedArray([])
  }

  const addNewBlog = async (blogObject) => {
    try {
      const result = await blogService.createBlog(blogObject)
      const result2 = await blogService.getUserBlogs(result.blog.slice(-1)[0])
      user.blog = user.blog.concat(result2)
      window.localStorage.setItem('loggedBlogUser', JSON.stringify(user))
      setBlogs(user.blog)
      setSortedArray(user.blog.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
      console.log("USER USER USER IS", user)
      setVisibility(false)
      setMsg(`a new blog ${blogObject.title} by ${user.name} added`)
      setTimeout(() => {
        setMsg('')
      },3000)
    }
    catch(error){
      console.log("error adding new blog", error)
    }
  }

  return (
    <div>
      <h2>blogs</h2>
      {msg !== '' && <h1 className='successMsg-container'>{msg}</h1>}
      {errorMsg !== '' && <h1 className='errorMsg-container'>{errorMsg}</h1>}
      {user == null && 
      <Login
        handleLogin={handleLogin}
        setUsername={setUsername}
        setPassword={setPassword}
        username={username}
        password={password}>
      </Login>
      }
      {user != null && <div className="notes">
        <p>{user.name} logged in <button onClick={handleLogout}>logout</button></p>
      </div>}
      {user != null && 
      <CreateBlog
        addNewBlog={addNewBlog}
        visibility={visibility} 
        setVisibility={setVisibility}>
      </CreateBlog>
      }
      {sortedArray !== null && sortedArray.map(blog =>
        <Blog key={blog.id} blog={blog} afterLikeClicked={(updatedBlog) => {
            const updatedBlogs = blogs.map((blog) => blog.id === updatedBlog.id ? updatedBlog : blog)
            //update original blogs
            setBlogs(updatedBlogs)
            //update sorted blogs
            setSortedArray(updatedBlogs.sort((a,b) => parseInt(b.likes) - parseInt(a.likes)))
        }} user={user} />
      )}
    </div>
  )
}

export default App

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

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