Search code examples
reactjsreact-context

Rewriting JS to TS leads to weird errors when it comes to React.Context


I have perfectly working and simple React JS context like below. Really, it can't be simpler.

import * as React from 'react';

export const SelectedCurrenciesContext = React.createContext();

const SelectedCurrenciesContextProvider = ({ children }) => {
    const [currencyBase, setCurrencyBase] = React.useState(null);
    const [currencyCrypto, setCurrencyCrypto] = React.useState(null);

    return (
        <SelectedCurrenciesContext.Provider
            value={{
                currencyBase: currencyBase,
                currencyCrypto: currencyCrypto,
                setCurrencyBase: data => setCurrencyBase(data),
                setCurrencyCrypto: data => setCurrencyCrypto(data),
            }}
        >
            {children}
        </SelectedCurrenciesContext.Provider>
    );
};

export default SelectedCurrenciesContextProvider;

Now try to have the same in Typescript and problems begin.

import * as React from 'react';
import { baseCurrencyType } from '../types';

type ContextType = {
    currencyBase?: baseCurrencyType | null;
    currencyCrypto?: string | null;
    setCurrencyBase?: (currencyBase: baseCurrencyType) => void;
    updateTodo?: (currencyCrypto: string) => void;
};

interface ContextTypeInterface {
    currencyBase?: baseCurrencyType | null;
    currencyCrypto?: string | null;
    setCurrencyBase?: (currencyBase: baseCurrencyType) => void;
    updateTodo?: (currencyCrypto: string) => void;
}

const InitialState = {
    currencyBase: null,
    currencyCrypto: null,
};
export const SelectedCurrenciesContext = React.createContext<ContextType | null>(null);

const SelectedCurrenciesContextProvider:React.FC = ({ children }) => {
    const [currencyBase, setCurrencyBase] = React.useState<baseCurrencyType | null>(null);
    const [currencyCrypto, setCurrencyCrypto] = React.useState<string | null>(null);

    return (
        <SelectedCurrenciesContext.Provider
            value={{
                currencyBase: InitialState.currencyBase,
                currencyCrypto: InitialState.currencyCrypto,
                setCurrencyBase: data => setCurrencyBase(data),
                setCurrencyCrypto: data => setCurrencyCrypto(data),
            }}
        >
            {children}
        </SelectedCurrenciesContext.Provider>
    );
};

export default SelectedCurrenciesContextProvider;

It throws basically two errors (technically more but guess the rest is generated be these two. The first error is at

    <SelectedCurrenciesContext.Provider

line and it says

Cannot find namespace 'SelectedCurrenciesContext'

The second one is at

const SelectedCurrenciesContextProvider = ({ children }) => {

and it says (what is probably consequence of first one)

children is declared but its value is never read

I have tried with or without defaultState( no success, seems it is a must) with defaultState being null, and also with passing state items not like above but only as

const [currencyBase, setCurrencyBase] = React.useState<baseCurrencyType | null>(null);

No matter how I do it, the errors does not vanish, however. Could someone help me?


Solution

  • 
    import React, { createContext, useState } from "react";
    
    interface SelectedCurrenciesContextProps {
        currencyBase?: baseCurrencyType;
        currencyCrypto?: string;
        setCurrencyBase: (currencyBase: baseCurrencyType) => void;
        setCurrencyCrypto: (currencyCrypto: string) => void;
    }
    const SelectedCurrenciesContext =  createContext<SelectedCurrenciesContextProps>({} as SelectedCurrenciesContextProps);
    
    function SelectedCurrenciesContextProvider ({ children }: { children: React.ReactNode }) {
        const [currencyBase, setCurrencyBase] = useState<baseCurrencyType | undefined>(undefined);
        const [currencyCrypto, setCurrencyCrypto] = useState<string | undefined>(undefined);
    
    // Same names will be recognized, no need to do currencyBase:currencyBase
    
        return (
            <SelectedCurrenciesContext.Provider
                value={{
                    currencyBase,
                    currencyCrypto,
                    setCurrencyBase,
                    setCurrencyCrypto,
                }}
            >
                {children}
            </SelectedCurrenciesContext.Provider>
        );
    }
    
    export {
     SelectedCurrenciesContextProps,
     SelectedCurrenciesContext,
     SelectedCurrenciesContextProvider
    };