如何从子组件调用 React Hook 来刷新结果

How to call a React Hook from a child component to refresh results

我正在尝试刷新页面上的结果,但刷新按钮位于最初调用我的 React Hook 的子组件中。

export const ParentComponent = ({

}) => {
  const infoINeed = useSelector(getInfoINeed);

  const { error, isLoading, data } = useMyAwesomeHook(infoINeed.name);

  return (
    <div>
      <Header/>
      <Body className={classes.body}>
        <div>Hello Stack overflow</div>
      <Body>
    </div>
  );
};

我的 Awesome 钩子看起来像这样

export const useDogCounts = (name: string | undefined) => {
  const { data: token, error: authError } = useAuthHook();
  const [error, setError] = useState<Error | null>(null);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    const fetchMyData = async () => {
      const request = myRequest(name);

      try {
        setLoading(true);
        const counts = callMyFunction()
        setMyData(counts);
        setLoading(false);
      } catch (requestError) {
        if (requestError === null) {
          setError(requestError);
        } else {
          throw requestError;
        }

        setLoading(false);
      }
    };

    fetchMyData();
  }, [name, token]);


  return {
    data: dogCounts,
    error,
    isLoading,
  };
};

然后在我的 <Header/> 组件中,我有一个要调用挂钩的刷新按钮。

import React, { FC } from 'react';
import { Button } from '@material-ui/core';

export const Header: FC<HeaderProps> = ({}) => {


  return (
    <Page.Header className={classes.headerWrapper}>
          <Page.Title>Dog Counts</Page.Title>
               <Button
                  onClick={() => {}} // functionality to go here
                >
                  Refresh
                </Button>
             
    </Header>
  );
};

我尝试了几种方法,包括将一个变量传递到名为 refresh 的 useDogCount 挂钩中,Header 组件会更改状态以触发我的主挂钩中的 useEffect 挂钩。这样做似乎有点乱,还要引入一个新的变量来跟踪。

我在其他时间也实现了类似的东西,我没有在我的自定义挂钩中使用 useEffect 挂钩,而是将 Promise 传回所需的位置以刷新它。但是,我需要 useEffect 挂钩来检查更新 nametoken.

现在,就触发数据请求而言,您的挂钩与任一组件之间没有任何联系。我的建议是向您的挂钩添加一个函数,该函数将调用您的 api 和 return 挂钩中的函数

export const useDogCounts = (name: string | undefined) => {
  const { data: token, error: authError } = useAuthHook();
  const [error, setError] = useState<Error | null>(null);
  const [isLoading, setLoading] = useState(true);

 const callAnApi = async () => {
  // ... body of the useEffect
 }

  useEffect(() => {
    const fetchMyData = async () => {
      const request = myRequest(name);

      try {
        setLoading(true);
        const counts = callMyFunction()
        setMyData(counts);
        setLoading(false);
      } catch (requestError) {
        if (requestError === null) {
          setError(requestError);
        } else {
          throw requestError;
        }

        setLoading(false);
      }
    };

    fetchMyData();
  }, [name, token]);


  return {
    data: dogCounts,
    error,
    isLoading,
  };
};

然后在你的ParentComponent中你可以将它解构为

const { error, isLoading, data, callAnApi } = useMyAwesomeHook(infoINeed.name);

并将其作为 prop 传递给 Header 组件,您只需将其用作

<Button
  onClick={callAnApiHandler}
>
  Refresh
</Button>

然后您可以在 useEffect 中调用这个新函数以进一步重构

您可以 return 用于从自定义挂钩中获取数据的函数:

export const ParentComponent = () => {
  const infoINeed = useSelector(getInfoINeed);

  const { error, isLoading, data, fetchData } = useMyAwesomeHook(infoINeed.name);

  return (
    <div>
      <Header onClickRefresh={fetchData}/>
      <Body className={classes.body}>
        <div>Hello Stack overflow</div>
      <Body>
    </div>
  );
};
export const useDogCounts = (name: string | undefined) => {
  const { data: token, error: authError } = useAuthHook();
  const [error, setError] = useState<Error | null>(null);
  const [isLoading, setLoading] = useState(true);

  const fetchData = useCallback(async () => {
    ... // code to fetch the data
  }, [name, token]);

  useEffect(fetchData, [fetchData]);

  return {
    data: dogCounts,
    fetchData,
    error,
    isLoading,
  };
};
export const Header: FC<HeaderProps> = ({onClickRefresh}) => {
  return (
    <Page.Header className={classes.headerWrapper}>
      <Page.Title>Dog Counts</Page.Title>
        <Button onClick={onClickRefresh}>
          Refresh
        </Button>
    </Header>
  );
};