2

I have a question about the implementation useFetch hook with typescript and Axios.

Here is I find some example useFetch hook. But It's a javascript implementation. I just gave there any to response and err.

https://codesandbox.io/s/react-fetch-hook-gtiec?from-embed=&file=/src/components/App.js

so here is my useFetch hook .ts file.

import { useState, useEffect } from 'react'

export const useFetch = ({
    api,
    method,
    url,
    data = null,
    config = null,
}: any) => {
    const [response, setResponse] = useState(null)
    const [error, setError] = useState('')
    const [isLoading, setIsLoading] = useState(true)

    useEffect(() => {
        const fetchData = async () => {
            api[method](url, JSON.parse(config), JSON.parse(data))
                .then((res : any) => {
                    setResponse(res.data)
                })
                .catch((err : any) => {
                    setError(err)
                })
                .finally(() => {
                    setIsLoading(false)
                })
        }

        fetchData()
    }, [api, method, url, data, config])

    return { response, error, isLoading }
}

and here is my component where I make fetch request via useFetch.

  const { response, isLoading, error } = useFetch({
        api: BaseURL,
        method: 'get',
        url: 'some',
    })

everything works well request is works. But when I try to pass to my some child component (child component wait string value) some string value from response.

here is the child component in the component where I make a fetch request.

return (
    <Title>{response && response.id}</Title>
)

here is the title component

type Props = {
    children: string
}
export const Title: FC<Props> = ({ children }) => {
    return <h4>{children}</h4>
}

I get this error:

Type 'null' is not assignable to type 'string | (string & {}) | (string & ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)>) | (string & ReactNodeArray) | (string & ReactPortal)'.ts(2322)
Object is possibly 'null'.ts(2531)

It's the first question of how I can implement this hook in a typescript way.

And here using fetch API. How I can use here Axios?

3
  • children: string | null Commented Jan 10, 2021 at 9:45
  • Do I need to add every type | null? I think it's not so correct, not? Commented Jan 10, 2021 at 9:46
  • response && response.id can be null (before request is completed), so you have 2 options: allow children to be null or provide some fallback (e.g. response?.id ?? '') Commented Jan 10, 2021 at 9:48

1 Answer 1

1

I think you currently have 2 problems need to resolve as following:

  • In your custom hook, you use a state const [response, setResponse] = useState(null) which tells response always null which can end up an issue where you check here {response && response.id}. So I suggest you to fill the type for response in generic type:
export const useFetch = <R extends any = any>({
  api,
  method,
  url,
  data = null,
  config = null,
}: any) => {
  const [response, setResponse] = useState<R | null>(null); // set `R` as returned type
  // ...
}

Then you specify your response where you use your custom hook:

const { response, isLoading, error } = useFetch<{ id: string }>({
  // ...
});
  • Another thing is to refine is the children type is supposed to be React.ReactNode
type Props = {
    children: React.ReactNode
}

Sign up to request clarification or add additional context in comments.

1 Comment

@user3348410 Side note: when you use FC no need to type children explicitly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.