繁体   English   中英

React Hook:使用自定义钩子处理 onClick 事件的正确方法?

[英]React Hook : Correct way of using custom hook to handle onClick Event?

正如标题所说,使用自定义钩子处理 onClick 事件的正确方法是什么?

当用户单击搜索按钮时,此 代码框应用程序将在屏幕上显示新报价。

function App() {
  const [{ data, isLoading, isError }, doFetch] = useDataApi(
    "https://api.quotable.io/random"
  );

  return (
    <Fragment>
      <button disabled={isLoading} onClick={doFetch}>
        Search
      </button>
      {isError && <div>Something went wrong ...</div>}
      {isLoading ? <div>Loading ...</div> : <div>{data.content}</div>}
    </Fragment>
  );
}

我创建了一个名为useDataApi()的自定义钩子,它将从 API 获取新报价。 为了在用户单击按钮时更新报价,在useDataApi()内,我创建了一个handleClick() ,它将更改单击值的值以触发重新渲染。 这个handleClick() function 将返回给App()

const useDataApi = initialUrl => {
  const [data, setData] = useState("");
  const [click, setClick] = useState(true);
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  const handleClick = () => {
    setClick(!click);
  };

  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);
      try {
        const result = await axios(initialUrl);

        setData(result.data);
      } catch (error) {
        setIsError(true);
      }
      setIsLoading(false);
    };
    fetchData();
  }, [initialUrl, click]);

  return [{ data, isLoading, isError }, handleClick];
};

这是可行的,但是,我认为这不是正确的解决方案。

我还尝试将fetchData()移出useEffect并返回fetchData() ,它也可以工作。 但是根据React Doc ,它说建议在useEffect中移动函数。

const useDataApi = initialUrl => {
  const [data, setData] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  const fetchData = async () => {
    setIsError(false);
    setIsLoading(true);
    try {
      const result = await axios(initialUrl);
      setData(result.data);
    } catch (error) {
      setIsError(true);
    }
    setIsLoading(false);
  };

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

  return [{ data, isLoading, isError }, fetchData];
};

此外,对于创建这些类型的应用程序,我使用的方式是好的还是有其他正确的解决方案,例如不使用任何useEffects或不创建任何自定义 Hook? 谢谢

不确定这是否正确,但这是我的解决方案。

const useDataApi = initialUrl => {
  const [data, setData] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  const doFetch = async () => {
    setIsError(false);
    setIsLoading(true);
    try {
      const result = await axios(initialUrl);

      setData(result.data);
    } catch (error) {
      setIsError(true);
    }
    setIsLoading(false);
  };

  return [{ data, isLoading, isError }, doFetch];
};

顺便说一句,不要直接变异 state 。

const handleClick = () => {
    setClick(!click);         // don't do this
    setClick(prev => !prev);    // use this
};

你的实现很好。 我们也在使用类似的东西。 希望你觉得它有用。

 function useApi(promiseFunction, deps, shouldRun=true){ // promisFunction returns promise const [loading, setLoading] = useState(false) const [data, setData] = useState(false) const [error, setError] = useState(false) const dependencies: any[] = useMemo(()=>{ return [...dependencyArray, shouldRun] },[...dependencyArray, shouldRun]) const reload = () => { async function call() { try { setError(null) setLoading(true) const res = await promiseFunction(); } catch (error) { setError(error) } finally { setLoading(false) } } call(); } useEffect(() => { if(,shouldRun) return setResult(null) //no stale data reload() }, dependencies) return {loading, error, data, reload: setState: setData} }

下面的代码将提供一些关于如何使用它的想法。

 function getUsersList(){ return fetch('/users') } function getUserDetail(id){ return fetch(`/user/${id}`) } const {loading, error, data } = useApi(getUsersList, [], true) const {loading: userLoading, error: userError, data: userData} = useApi(()=>getUserDetail(id), [id], true)

暂无
暂无

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

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