Currently, I have a custom fetching data hook written in javascript and it works
import {useState, useEffect} from 'react';
const useApi = apiName => id => {
const [response, setResponse] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const fetching = async () => {
setLoading(true);
const data = await fetch(`/api/${apiName}${id ? `/${id}` : ""}`)
.then((x) => x.json())
.catch((error) => setError(error));
setResponse(data);
setLoading(false);
};
useEffect(() => {
fetching();
}, [id]);
return { response, loading, error };
};
Then I can use pass in what api I want to call to get the hook. For examples:
const useCustomer = useApi("customer")
const useHello = useApi("hello")
.....
const {response, loading, error} = useCustomer("id_1")
It works fine.
Then, I try to convert to typescript
const useApi = (apiName:string) => (id?:string) => {
const [response, setResponse] = useState({})
.......
}
and eslint complains that
React Hook "useState" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
I would like to know whats wrong with this approach, I know I can have something like:
const useApi = (apiName:string, id?:string) => {}
or disable the eslint(react-hooks/rules-of-hooks)
But just curious about whats the potential problems having higher order function of hook since it actually return the response.
Thanks
When you name you function with prefix
hooks, eslint thinks of it as a custom hook according to the general convention. Now that implements useState in a nested function which is why it gives you an error
The best way to write the above code is to not use currying function but pass in the apiName as a param directly
const useApi = (apiName, id) => {
const [response, setResponse] = useState();
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const fetching = async () => {
setLoading(true);
const data = await fetch(`/api/${apiName}${id ? `/${id}` : ""}`)
.then((x) => x.json())
.catch((error) => setError(error));
setResponse(data);
setLoading(false);
};
useEffect(() => {
fetching();
}, [id]);
return { response, loading, error };
};
and use it like
.....
const {response, loading, error} = useApi("customer","id_1");
PS Hooks are meant to be an alternative to HOC's and there is no point writing a hook if you use it as an HOC itself
There's a much easier way if you don't need the id variable to be in the hook. The reason why you get the warning is because your hooks are in your CB instead of your root function.
Correct Example:
const useApi = (apiName:string) => {
const [response, setResponse] = useState({});
return (id?: string) => {
.......
};
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.