LikeAKemper
LikeAKemper

Reputation: 155

Custom Hook - return state and set state

I am trying to use a custom hook similarly as described here: https://www.robinwieruch.de/react-hooks-fetch-data

This is my custom hook:

export const useProcesses = (id: string, token: string, enqueueSnackbar: NotificationFunction) => {
    const [processes, setProcesses] = useState<ProcessDTO[]>([]);
    const [isLoading, setIsLoading] = useState(false);
    const [isError, setIsError] = useState(false);

    useEffect(() => {
        const fetchProcesses = async () => {
            setIsError(false);
            setIsLoading(true);
            try {
                if (id !== undefined) {
                    const response = await new HttpService()
                        .withToken(token)
                        .get(createProcessesPathForIdEndpoint(id), enqueueSnackbar);

                    const data = response.data.data;
                    setProcesses(data);
                    return data;
                }
            } catch {
                setIsError(true);
            }
            setIsLoading(false);
        };

        fetchProcesses();
    }, [enqueueSnackbar, id, token]);
    return [{ Processes, isLoading, isError }, setProcesses];
    };

I am accessing the hook as:

    const [{ processes, isLoading, isError }, setProcesses] = useProcesses(
    id,
    token,
    enqueueSnackbar,
);

The typescript error received is:

Property 'Processes' does not exist on type 'Dispatch<SetStateAction<ProcessDTO[]>> | { Processes: ProcessDTO[]; isLoading: boolean; isError: boolean; }'.  TS2339

Does anyone see what I'm doing wrong here?

Upvotes: 2

Views: 1517

Answers (1)

Paul Huynh
Paul Huynh

Reputation: 3190

Seems like Typescript isn't inferring the return type in the way that you want it. It fails for simple examples too, like this one:

const thingy = () => {
    return ['abc', 9, 'abcd']
}
const [a, b, c] = thingy() // a, b, and c are all of type 'string|number'

We need to to give Typescript a little help, so we explicitly declare the return type, which will allow the variables a b c to have the correct types:

const thingy = (): [string, number, string] => {
    ...

For your code, you'll want something like this:

type UseProcessesResult = [
    {
        processes: ProcessDTO[],
        isLoading: boolean,
        isError: boolean,
    },
    Dispatch<SetStateAction<ProcessDTO[]>>,
]
export const useProcesses = (id: string, token: string, enqueueSnackbar: NotificationFunction): UseProcessesResult {
    ...

Upvotes: 4

Related Questions