Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React TS useContext useReducer hook

I can't figure out what the type error is in this code

import React from 'react';

interface IMenu {
  items: {
    title: string,
    active: boolean,
    label: string
  }[]
}


type Action =
  | { type: 'SET_ACTIVE', label: string }

const initialState: IMenu = {
  items: [
    { title: 'Home', active: false, label: 'home' },
    { title: 'Customer', active: false, label: 'customer' },
    { title: 'Employee', active: false, label: 'employee' },
    { title: 'Report', active: false, label: 'report' },
  ]
}

const reducer = (state: IMenu = initialState, action: Action) => {
  switch (action.type) {
    case 'SET_ACTIVE': {
      const label = action.label;
      const items = state.items.map((item) => {
        if (item.label === label) {
          return { ...item, active: true };
        }
        return { ...item, active: false }
      })
      return { items }
    }
    default:
      throw new Error();
  }
};

export const MenuContext = React.createContext(initialState);
export const MenuConsumer = MenuContext.Consumer;

export function MenuProvider(props: any) {
  const [state, dispatch] = React.useReducer(reducer, initialState)
  const value = { state, dispatch };
  console.log(value)
  return (
    <MenuContext.Provider value={value}>
      {props.children}
    </MenuContext.Provider>
  )
}

The error I receive is this

    /Volumes/Tarang External/react-context-typescript/src/context/index.tsx
TypeScript error in /Volumes/Tarang External/react-context-typescript/src/context/index.tsx(49,27):
Property 'items' is missing in type '{ state: { items: { active: boolean; title: string; label: string; }[]; }; dispatch: Dispatch<{ type: "SET_ACTIVE"; label: string; }>; }' but required in type 'IMenu'.  TS2741

    47 |   console.log(value)
    48 |   return (
  > 49 |     <MenuContext.Provider value={value}>
       |                           ^
    50 |       {props.children}
    51 |     </MenuContext.Prov

Can someone help point out what exactly I'm doing wrong? I am new to typescript so please guide me if necessary. I am trying to pass the context value of state and dispatch to the child component. I am not sure what's going. Is this also a correct way to implement useContext and useReducer hooks?

like image 489
Tarang Hirani Avatar asked Jul 31 '19 20:07

Tarang Hirani


People also ask

What is difference between useContext and useReducer?

js import { createContext, useReducer } from "react"; The useReducer hook is pretty similar to a useState hook. The only difference is that a useReducer requires as arguments a reducer and an initialState , and is preferred when we deal with complex state logic.

Can I use useContext in custom hook?

Create the useContextInside of this custom hook, we'll be using the useContext hook, that allows us to access both the theme and the setTheme function outside of this file.

How do I use useReducer and useContext?

Instead of passing the props down through each component, React Context allows you to broadcast props to the components below. The useReducer hook is used for complex state manipulations and state transitions. … useReducer is a React hook function that accepts a reducer function, and an initial state.

Is useContext a react hook?

The useContext hook is the new addition in React 16.8. Syntax: const authContext = useContext(initialValue); The useContext accepts the value provided by React.


1 Answers

Your problem is that your context is supposed to have the same type as initialState, but instead, you set your context's default value to { state, dispatch }.

This is incorrect.

To solve, either set your context's default type to { state, dispatch } (I think this is what you want, or set the context's default type to typeof initialState.

Here's the solution.

like image 178
Tejas Avatar answered Sep 20 '22 18:09

Tejas