使用useEffect反应axios获取请求而不会导致无限循环

时间:2020-06-27 17:12:16

标签: reactjs mongodb axios react-hooks use-effect

此axios get请求使我陷入无限循环,但是当我尝试在useEffect末尾将message或setMessages作为[]内的值时,需要单击两次按钮以更新屏幕或它导致错误,提示网络资源不足。那我该放什么呢?

function CommentsPage() {
  const { user } = useAuth0();

  const [query, setQuery] = useState("");
  const [messages, setMessages] = useState([]);

  //fetches data from mongodb for comments
  useEffect(() => {
    fetchComments();
  }, [messages]);

  //calls backend to fetch data from the messages collection on mongodb
  async function fetchComments() {
    const response = await axios.get("http://localhost:5000/messages");

    setMessages(response.data);
  }

  // handles when a user types in the comment bar
  function handleOnInputChange(event) {
    // current value of what user is typing
    const { value } = event.target;

    setQuery(value);
  }

  // handles when a user posts a comment
  function postComment(comment, user) {
    const newMessage = {
      username: user.name,
      content: comment,
    };

    // calls backend to send a post request to insert a new document into the collection
    axios
      .post("http://localhost:5000/messages", newMessage)
      .then((res) => console.log(res.data));

    setQuery("");
    fetchComments();
  }

  // handles when a user deletes a comment
  function deleteComment(id) {
    axios
      .delete("http://localhost:5000/messages/delete/" + id)
      .then((res) => console.log(res.data));

    fetchComments();

    setMessages(messages.filter((message) => message.id !== id));
  }

  // handles when a user updates a comment
  function updateComment(id) {
    // calls a pop up that allows user to input their new comment
    const editedContent = prompt("please enter new message");

    const newMessage = {
      username: user.name,
      content: editedContent,
    };

    axios
      .put("http://localhost:5000/messages/update/" + id, newMessage)
      .then((res) => console.log(res.data));

    fetchComments();
  }

  console.log(messages);

  return (
    <Container>
      <CommentsContainer>
        {messages.length ? (
          messages.map((message) => {
            {/* if the usernames match then a user comment is returned
            otherwise an other comment will be returned */}
            return message.username === user.name ? (
              <UserComment
                key={message._id}
                username={message.username}
                content={message.content}
                deleteComment={deleteComment}
                id={message._id}
                updateComment={updateComment}
              />
            ) : (
              <OtherComment
                key={message._id}
                username={message.username}
                content={message.content}
              />
            );
          })
        ) : (
          <div>There are no comments. Make one!</div>
        )}
      </CommentsContainer>
      <CommentBarStyle htmlFor="search-input">
        <input
          name="commentBar"
          type="text"
          value={query}
          id="search-input"
          placeholder="Write a comment..."
          onChange={handleOnInputChange}
        />
        <AddIcon
          className="fas fa-plus"
          onClick={() => postComment(query, user)}
        />
      </CommentBarStyle>
    </Container>
  );
}

export default CommentsPage;

2 个答案:

答案 0 :(得分:0)

您正在更新fetchComments内的“消息”状态...因此,每次更新此状态时,都会调用useEffect,因为它具有消息作为依赖项。

  useEffect(() => {
    fetchComments();
  }, [messages]);

  //calls backend to fetch data from the messages collection on mongodb
  async function fetchComments() {
    const response = await axios.get("http://localhost:5000/messages");

    setMessages(response.data);
  }

尝试一下:

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

如果以此方式进行操作,则组件将在安装阶段调用fetchComments,而不是在每次消息状态更改时都调用它。

答案 1 :(得分:0)

您的useEffect将在每次消息状态更改时运行。像这样更改useEffect:

useEffect(() => {
    fetchComments();
},[null]);