Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

reactjs - How do I make my post load only if it has been fetched

Each time I open a new post page, the data from the last post shows on the screen for a couple of miliseconds and then the new data is shown. I have tried to check if the post is loading and set it in the state with the setIsLoading function, but it does not work. See the code below:

const PostPage = ({post, setPost, isLoading, setIsLoading}) => {
  const location = useLocation()
  const pathname = location.pathname.split("/")[2]

  useEffect(() => {
    setIsLoading(true)
    const fetchData = async () => {
      let res = await axios.get(`http://localhost:4000/posts/${pathname}`)
      const postData = res.data
      setPost(postData)
      setIsLoading(false)
    }
    fetchData()
  }, [])

  return (
    <>
      {!isLoading && (
        <div>
          <h1>{post.title}</h1>
          <p>{post.text}</p>
        </div>
      )}
    </>
  )
}

These are my routes:

<Switch>
          <Route path="/" exact>
            {isLogged && (
              <AddPost
                posts={posts}
                setPosts={setPosts}
                postTitle={postTitle}
                setPostTitle={setPostTitle}
                postText={postText}
                setPostText={setPostText}
                setIsLoading={setIsLoading}
              />
            )}
            <div className="posts-row">
              {posts.slice(0).reverse().map(post => (
                <Post
                  key={post.id}
                  id={post.id}
                  postTitle={post.title}
                  postText={post.text}
                  isLogged={isLogged}
                  posts={posts}
                  setPosts={setPosts}
                  />
              ))}
            </div>
          </Route>
          <Route path="/posts/:id" exact>
            <PostPage
              post={post}
              setPost={setPost}
              isLoading={isLoading}
              setIsLoading={setIsLoading}
            />
          </Route>
        </Switch>

In App.js I have isLoading set to true, but it works only for the first post. For the sake of React please don't report my question :D

Edit: Post.js

const Post = ({postTitle, postText, isLogged, posts, setPosts, id}) => {

  const removePost = async (id) => {
    const postArray = posts.filter((post) => (post.id !== id))
    let res = await axios.delete(`http://localhost:4000/posts/${id}`)
    setPosts(postArray)
  }

  return (
    <div className="post">
      <Link to={`/posts/${id}`}>
        <strong>
          {postTitle}
        </strong>
      </Link>
      <p>{postText}</p>
      {isLogged && (
        <button onClick={() => removePost(id)}>
          ???
        </button>
      )}
    </div>
  )
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your effect hook only runs when the component is mounted for the first time. If you want to run it every time pathname changes, add it to its dependency array:

useEffect(() => {
  setIsLoading(true)
  const fetchData = async () => {
    let res = await axios.get(`http://localhost:4000/posts/${pathname}`)
    const postData = res.data
    setPost(postData)
    setIsLoading(false)
  }
  fetchData()
}, [pathname])

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...