如何在事件处理程序中使用自定义钩子?

时间:2019-10-14 21:55:13

标签: javascript reactjs event-handling fetch react-hooks

我创建了一个自定义的Hook,该Hook从服务器获取数据,将分派发送到商店并返回数据。如果我想在我的应用程序中列出所有评论,这是可用的,但是,我想在需要获取所有评论回复的组件中重用它,并且只有在单击某些按钮时才应该发生。

这是下面的钩子。

import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";

const useFetch = (url, options, actionType, dataType) => {
  const [response, setResponse] = useState([]);

  const dispatch = useDispatch();
  useEffect(() => {
    (async () => {
      const res = await fetch(url);
      const json = await res.json();
      setResponse(json);
    })();
  }, []);

  useEffect(() => {
    dispatch({ payload: response, type: actionType });
  }, [response]);
  const data = useSelector(state => state[dataType]);

  return data;
};

export default useFetch;

在我的组件内部,当单击按钮时,我需要获取答复

const ParentComment = ({ comment }) => {
  const handleShowMoreReplies = (e) => {
    e.preventDefault();

}
  let replies = useFetch(
    `/api/comment_replies?comment_id=${comment.id}`,
    null,
    "REPLIES_RECEIVED",
    "replies"
  );
  return (
    <div>
      <Comment comment={comment} />
      <div className="replies">
        {replies.map(reply => (
          <Comment key={reply.id} comment={reply} />
        ))}
          <a href="#" className="show_more" onClick={handleShowMoreReplies}>
            Show More Replies ({comment.replies_count - 1})
          </a>
      </div>
    </div>
  );
};

如果我将useFetch调用放入处理程序中,则会收到一个错误,指出无法在此处调用Hooks,但仅在单击按钮时才需要调用它,所以我不知道是否存在一种实现方式。

1 个答案:

答案 0 :(得分:1)

我认为您的useFetch钩子有一些细微的问题

1。您的useEffect具有需要定义的$ {url}和$ {actionType}的部门。

2。为了通过单击按钮调用此挂钩,您需要按如下所示公开setUrl

const useFetch = ( initialUrl, options, actionType, dataType) => {
  const [url, setUrl ] = useState(initialUrl);

  const dispatch = useDispatch();
  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url);
        const data = await res.json();
        dispatch({ payload: data, type: actionType });
      } catch (error) {
       console.log(error);
      }
    };
    fetchData();
  }, [url, actionType]);

  const data = useSelector(state => state[dataType]);
  return [ data, setUrl ];
};

export default useFetch;

然后,当您尝试使用此挂钩时,可以

const [data, fetchUrl] = useFetch(
  `/api/comment_replies?comment_id=${comment.id}`,
  null,
  "REPLIES_RECEIVED",
  "replies"
);

然后,每当您有一个按钮时,您都可以简单地致电

fetchUrl(${yourUrl}). 

您的钩子将收到新的URL,它是钩子的dep并重新呈现。

这是相关的文章 https://www.robinwieruch.de/react-hooks-fetch-data