首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >useFetch自定义钩子+去弹反应

useFetch自定义钩子+去弹反应
EN

Stack Overflow用户
提问于 2020-10-06 14:01:17
回答 1查看 480关注 0票数 0

目标:创建一个可重用的useFecth自定义钩子+取消组件,这样在每次击键之后,API就不会在用户键入代码框中的示例之后得到调用。

我所拥有的:

  1. 输入标记,该标记将触发退选函数。
  2. 在执行new函数之后,它将设置一个新值并触发useFetch自定义钩子。
  3. 执行自定义钩子并进行API调用。

问题是:如果值(狗品种)输入错误或提供一个不存在的值(狗品种),它将抛出我正在处理的useFetch钩子中的错误。到目前为止,问题是,如果我想传递另一个值(狗品种),它仍然抛出不存在的错误,当它不应该。感觉就像卡在那里了,不会重新呈现。

代码语言:javascript
复制
import useFetch from "./useFetch";
import IsLoadingComponent from "./isLoadingComponent";

export default function App() {
  const [value, setValue] = useState("");
  const [dogBreed, setDogBreed] = useState("");

  //custom fetch hook
  //will be trigger after debounce function is done executing
  const url = `https://dog.ceo/api/breed/${dogBreed}/images/random`;

  const { data: randomImage, isLoading, hasError, errorMessage } = useFetch(
    url,
    dogBreed
  );

  //debounce the value after user is done typing not after every keystroke
  const debouncedSave = useCallback(
    debounce((nextDogBreed) => setDogBreed(nextDogBreed), 500),
    [] // will be created only once initially
  );

  //this will trigger the debounce function
  const handleChange = (e) => {
    const { value: nextDogBreed } = e.target;
    setValue(nextDogBreed);

    debouncedSave(nextDogBreed);
  };

  // console.log(dogBreed);
  // console.log(randomImage);
  // console.log(hasError);
  // console.log(errorMessage);

  return (
    <div className="App">
      <input placeholder="breed" onChange={handleChange} />
      <br />
      {isLoading ? (
        <IsLoadingComponent />
      ) : hasError ? (
        <h1>{errorMessage.message}</h1>
      ) : (
        <img
          src={randomImage}
          alt="dogImage"
          style={{ width: "200px", height: "200px", marginTop: "2rem" }}
        />
      )}
    </div>
  );
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

useFetch自定义钩

代码语言:javascript
复制
import { useState, useEffect } from "react";

const useFetch = (url, dogBreed) => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [hasError, setHasError] = useState(false);
  const [errorMessage, setErrorMessage] = useState("");

  useEffect(() => {
    if (dogBreed) {
      const fetchData = async () => {
        setIsLoading(true);
        try {
          const response = await fetch(url);
          const result = await response.json();
          if (response.ok) {
            setData(result.message);
          } else {
            setHasError(true);
            setErrorMessage(result);
          }
        } catch (err) {
          setHasError(true);
          setErrorMessage(err.message);
        } finally {
          setIsLoading(false);
        }
      };
      fetchData();
    } else {
      setData("https://images.dog.ceo/breeds/african/n02116738_10215.jpg ");
    }
  }, [url, dogBreed]);
  return { data, isLoading, hasError, errorMessage };
};
export default useFetch;

谢谢你的帮助

EN

回答 1

Stack Overflow用户

发布于 2021-04-12 23:33:06

使用缓存和删除自定义获取。

代码语言:javascript
复制
    const debounce = (fn: any, time: any) => {
    let timer: any;
    return (...args: any) => {
        if(timer) clearTimeout(timer)
        timer = setTimeout(()=> {
            timer = null
            fn(args)
        }, time)
    }
}
const useFetch = (num: string) => {
    const [data, setData] = useState({})
    const [error, setError] = useState('')
    const [loading, setLoading] = useState(false)
    const cache = useRef<Map<string, {}>>(new Map())



    useEffect(() => {
        async function call() {
            if(cache.current.has(num)){
                const d = cache.current.get(num) as {}
                setData(d)
            }else{
                try{
                    setLoading(true)
                    const r = await axios(`https://jsonplaceholder.typicode.com/posts/${num}`)
                    setData(r.data)
                    cache.current.set(num, r.data)
                }catch(err){
                    setError('Request failed')
                    setData({})
                }finally{
                    setLoading(false)
                }
            }
            
        }
        if(num.length){
            call()
        }else{
            setData({})
            setLoading(false)
        }
    },[num])

    return [data, error, loading]
}   


const Component = () => {
    const [value, setValue] = useState('')
    const [resp, setData] = useState({})
    const [debouncedTerm, setDebouncedTerm] = useState('')
    const [data, error, loading] = useFetch(debouncedTerm);


    const cb = useCallback(debounce((v: string) => setApiCallVal(v), 1000),[])

    const changeHandler = (e: ChangeEvent<HTMLInputElement>) => {
        setValue(e.target.value)
        cb(e.target.value)
    }    



    if(loading) return <p>Loading...</p>
    return (
        <section className="container">
            <section className="header-wrapper">
                <h1>Fetch + Debounce</h1>
            <input onChange={changeHandler} value={value} />
                <p>{JSON.stringify(data)}</p>
                {error}
            </section>
        </section>
    )
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64227405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档