Home > Blockchain >  How to use TypeScript with a custom hook for reactjs useContext?
How to use TypeScript with a custom hook for reactjs useContext?

Time:11-09

I'm trying to refactor my context to use a custom hook in TypeScript and I've got an error I don't know how to fix.

This is the error:

This expression is not callable. Not all constituents of type 'boolean | Dispatch<SetStateAction>' are callable. Type 'false' has no call signatures. TS2349

My custom hook is defined like this:

export const useOfflineContext = () => {
  const isOffline = React.useContext(OfflineContext);
  const setIsOffline = React.useContext(OfflineSetContext);

  if (!setIsOffline) {
    throw new Error('The OfflineProvider is missing.');
  }
  return [isOffline, setIsOffline];
};

And I'm calling it like this:

  const [setIsOffline] = useOfflineContext();

  // Check if we are online or offline.
  useEffect(() => {
    Network.addListener('networkStatusChange', (networkStatus) => {
      // console.log('Network status changed', networkStatus);
      if (!networkStatus.connected) {
        setIsOffline(true);

This causes the error above.

Here's my full component OfflineContextProvider.tsx:

import React, { useState } from 'react';

const OfflineContext = React.createContext(false);
const OfflineSetContext = React.createContext({} as React.Dispatch<React.SetStateAction<boolean>>);

interface MyProps {
  children: JSX.Element,
}

export const OfflineContextProvider: React.VFC<MyProps> = ({ children }: MyProps) => {
  const [isOffline, setIsOffline] = useState<boolean>(false);

  return (
    <OfflineContext.Provider value={isOffline}>
      <OfflineSetContext.Provider value={setIsOffline}>
        {children}
      </OfflineSetContext.Provider>
    </OfflineContext.Provider>
  );
};

export const useOfflineContext = () => {
  const isOffline = React.useContext(OfflineContext);
  const setIsOffline = React.useContext(OfflineSetContext);

  if (!setIsOffline) {
    throw new Error('The OfflineProvider is missing.');
  }
  return [isOffline, setIsOffline];
};

I don't understand why, when I specifically ask for const [setIsOffline] = useOfflineContext();, TypeScript thinks that I might want isOffline instead. (Because the TypeScript warning mentions the boolean value (isOffline).)

So my question is: How can I properly type useState when used in a custom hook to return a context?

Currently using TypeScript 4.3.

CodePudding user response:

You're using the first element of the returned array, which is isOffline (a boolean), but you're calling it setIsOffline. However, it is still a boolean.

What you probably want is to get the second element of the array:

const [ , setIsOffline ] = useOfflineContext();
  • Related