简体   繁体   English

父组件重新渲染 useEffect

[英]Parent component rerender useEffect

I have a parent Component named Posts that has a useEffect and fetches data, then I have a child component named Post which renders the post from props.我有一个名为 Posts 的父组件,它有一个 useEffect 并获取数据,然后我有一个名为 Post 的子组件,它从 props 渲染帖子。 I have a delete and like function inside Post and I want the parent to rerender when post get liked or post gets deleted.我在 Post 中有一个删除和喜欢功能,我希望父级在帖子被喜欢或帖子被删除时重新呈现。 How can I achieve this?我怎样才能做到这一点?

const Posts = () => {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    getPosts();
  }, []);

  const getPosts = async () => {
    const data = await fetch('https://localhost:1111/api/posts/posts', {
      credentials: 'include'
    });
    const response = await data.json();
    console.log(response);
    setPosts(response);
  };

  return (
    <div>
      {posts.map(post => (
        <Post key={post.id} post={post} />
      ))}
    </div>
  );
};

const Post = props => {
  const like = async post => {
    const formData = new FormData();
    formData.append('id', post);
    const data = await fetch('https://localhost:1111/api/posts/like', {
      method: 'POST',
      body: formData,
      credentials: 'include'
    });

    const response = await data.json();
    console.log(response);
  };

  const deletePost = async post => {
    const formData = new FormData();
    formData.append('id', post);
    const data = await fetch('https://localhost:1111/api/posts/deletepost', {
      method: 'POST',
      body: formData,
      credentials: 'include'
    });

    const response = await data.json();
    console.log(response);
  };

  return (
    <div>
      <img
        src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
        alt={`Post ${props.post.id}`}
      />
      <button onClick={() => like(props.post.id)}>Like</button>
      <button onClick={() => deletePost(props.post.id)}>Delete</button>
    </div>
  );
};

I would recommend you to have an additional prop method ( onUpdate ) on the child <Post /> component, which gets triggered whenever the deletePost() or like() are triggered.我建议您在子<Post />组件上有一个额外的 prop 方法( onUpdate ),只要触发deletePost()like()触发它。

const Posts = () => {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    getPosts();
  }, []);

  const getPosts = async () => {
    const data = await fetch('https://localhost:1111/api/posts/posts', {
      credentials: 'include'
    });
    const response = await data.json();
    console.log(response);
    setPosts(response);
  };

 const handleUpdate = () => {
   getPosts();
 }

  return (
    <div>
      {posts.map(post => (
        <Post key={post.id} onUpdate={() => handleUpdate()} post={post} />
      ))}
    </div>
  );
};

const Post = props => {
  const { onUpdate } = props;

  const like = async post => {
    const formData = new FormData();
    formData.append('id', post);
    const data = await fetch('https://localhost:1111/api/posts/like', {
      method: 'POST',
      body: formData,
      credentials: 'include'
    });

    const response = await data.json();
    console.log(response);

    onUpdate();
  };

  const deletePost = async post => {
    const formData = new FormData();
    formData.append('id', post);
    const data = await fetch('https://localhost:1111/api/posts/deletepost', {
      method: 'POST',
      body: formData,
      credentials: 'include'
    });

    const response = await data.json();
    console.log(response);

    onUpdate();
  };

  return (
    <div>
      <img
        src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
        alt={`Post ${props.post.id}`}
      />
      <button onClick={() => like(props.post.id)}>Like</button>
      <button onClick={() => deletePost(props.post.id)}>Delete</button>
    </div>
  );
};

As you can see, onUpdate() is called at the end of both deletePost() and like() , and on the parent Posts component, handleUpdate() will be called, which in turn submits the fetch response to update the posts state.如您所见, onUpdate()deletePost()like()的末尾被调用,并且在父 Posts 组件上, handleUpdate()将被调用,它依次提交 fetch 响应以更新posts状态。 This will cause the parent <Posts /> to re-render.这将导致父<Posts />重新渲染。

Keep post functionality inside the parent component and pass the update functions to Post将 post 功能保留在父组件中,并将更新函数传递给Post

const Posts = () => {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    fetch('https://localhost:1111/api/posts/posts', {
      credentials: 'include',
    })
      .then(res => res.json())
      .then(setPosts)
  }, [])

  const likePost = async postId => {
    await fetch...
    setPosts(prevState =>
      prevState.map(post =>
        post.id === postId
          ? {
              ...post,
              likes: post.likes + 1,
            }
          : post
      )
    )
  }

  const deletePost = async postId => {
    await fetch...
    setPosts(prevState => prevState.filter(post => post.id !== postId))
  }

  return (
    <div>
      {posts.map(post => (
        <Post
          key={post.id}
          post={post}
          likePost={likePost}
          deletePost={deletePost}
        />
      ))}
    </div>
  )
}

const Post = ({ post, likePost, deletePost }) => (
  <div>
    <img
      src={`http://localhost:1111/api/posts/uploads/images/${post.content}`}
      alt={`Post ${post.id}`}
    />
    <button onClick={() => likePost(post.id)}>Like</button>
    <button onClick={() => deletePost(post.id)}>Delete</button>
  </div>
)

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

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