父组件重新渲染 useEffect

huangapple go评论77阅读模式
英文:

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. I have a delete and like function inside Post and I want the parent to rerender when post gets liked or post gets deleted. 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 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. I have a delete and like function inside Post and I want the parent to rerender when post get liked or post gets deleted. How can I achieve this?

const Posts = () =&gt; {
const [posts, setPosts] = useState([]);
useEffect(() =&gt; {
getPosts();
}, []);
const getPosts = async () =&gt; {
const data = await fetch(&#39;https://localhost:1111/api/posts/posts&#39;, {
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
setPosts(response);
};
return (
&lt;div&gt;
{posts.map(post =&gt; (
&lt;Post key={post.id} post={post} /&gt;
))}
&lt;/div&gt;
);
};
const Post = props =&gt; {
const like = async post =&gt; {
const formData = new FormData();
formData.append(&#39;id&#39;, post);
const data = await fetch(&#39;https://localhost:1111/api/posts/like&#39;, {
method: &#39;POST&#39;,
body: formData,
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
};
const deletePost = async post =&gt; {
const formData = new FormData();
formData.append(&#39;id&#39;, post);
const data = await fetch(&#39;https://localhost:1111/api/posts/deletepost&#39;, {
method: &#39;POST&#39;,
body: formData,
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
};
return (
&lt;div&gt;
&lt;img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/&gt;
&lt;button onClick={() =&gt; like(props.post.id)}&gt;Like&lt;/button&gt;
&lt;button onClick={() =&gt; deletePost(props.post.id)}&gt;Delete&lt;/button&gt;
&lt;/div&gt;
);
};

答案1

得分: 1

I would recommend you to have an additional prop method (onUpdate) on the child &lt;Post /&gt; component, which gets triggered whenever the deletePost() or like() are triggered.

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. This will cause the parent &lt;Posts /&gt; to re-render.

英文:

I would recommend you to have an additional prop method (onUpdate) on the child &lt;Post /&gt; component, which gets triggered whenever the deletePost() or like() are triggered.

const Posts = () =&gt; {
const [posts, setPosts] = useState([]);
useEffect(() =&gt; {
getPosts();
}, []);
const getPosts = async () =&gt; {
const data = await fetch(&#39;https://localhost:1111/api/posts/posts&#39;, {
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
setPosts(response);
};
const handleUpdate = () =&gt; {
getPosts();
}
return (
&lt;div&gt;
{posts.map(post =&gt; (
&lt;Post key={post.id} onUpdate={() =&gt; handleUpdate()} post={post} /&gt;
))}
&lt;/div&gt;
);
};
const Post = props =&gt; {
const { onUpdate } = props;
const like = async post =&gt; {
const formData = new FormData();
formData.append(&#39;id&#39;, post);
const data = await fetch(&#39;https://localhost:1111/api/posts/like&#39;, {
method: &#39;POST&#39;,
body: formData,
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
onUpdate();
};
const deletePost = async post =&gt; {
const formData = new FormData();
formData.append(&#39;id&#39;, post);
const data = await fetch(&#39;https://localhost:1111/api/posts/deletepost&#39;, {
method: &#39;POST&#39;,
body: formData,
credentials: &#39;include&#39;
});
const response = await data.json();
console.log(response);
onUpdate();
};
return (
&lt;div&gt;
&lt;img
src={`http://localhost:1111/api/posts/uploads/images/${props.post.content}`}
alt={`Post ${props.post.id}`}
/&gt;
&lt;button onClick={() =&gt; like(props.post.id)}&gt;Like&lt;/button&gt;
&lt;button onClick={() =&gt; deletePost(props.post.id)}&gt;Delete&lt;/button&gt;
&lt;/div&gt;
);
};

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. This will cause the parent &lt;Posts /&gt; to re-render.

答案2

得分: 0

Keep post functionality inside the parent component and pass the update functions to 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>
)
英文:

Keep post functionality inside the parent component and pass the update functions to Post

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

  useEffect(() =&gt; {
    fetch(&#39;https://localhost:1111/api/posts/posts&#39;, {
      credentials: &#39;include&#39;,
    })
      .then(res =&gt; res.json())
      .then(setPosts)
  }, [])

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

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

  return (
    &lt;div&gt;
      {posts.map(post =&gt; (
        &lt;Post
          key={post.id}
          post={post}
          likePost={likePost}
          deletePost={deletePost}
        /&gt;
      ))}
    &lt;/div&gt;
  )
}

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

huangapple
  • 本文由 发表于 2020年1月3日 22:45:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580540.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定