简体   繁体   中英

Type '{ state: any; dispatch: React.Dispatch<{ type: string; value: any; }>; }' is not assignable to type

I'm building a UI that has some checkbox(s) on the left side and a data table on the right side, and drop zone box, I want to be able to maintain the table data every time I drop a new file and there, and filter the data in the table based on the checkbox(s) selection, anyway, I built most of that, and I was able to pass the selection controls to the the main component to filter/sort data, later I tried to add redux to maintain the state of the application, but it didn't work smoothly with hooks and it kept complaining about calling hooks from outside of the function component body, although they were not. I came to conclusion that they don't work nicely together and switched gears to use context and redux together to maintain the state and build this component, but I'm having a compilation issue, it's been 2 years since I used react/hooks/redux and I feel like things changed over the last 2 years.

**) Is my conclusion about the conflict between redux and hooks right? if not, could you please throw some light at it?

Below is the code and the error, the line that has the issue is return <Provider value={{ state, dispatch }}>{children}</Provider>;

store.tsx

 // store.js import React, {createContext, useReducer} from 'react'; import { useDispatch } from 'react-redux' import DataRow from '../types/datarow'; //define empty filters array const initFilter: string[] = []; const initDataRows: DataRow[] = []; const initialState = { searchFilter: initFilter, dataRows: initDataRows }; // const dispatch: React.Dispatch<{ // type: string; // value: any; // }>= {}; //const dispatch = useDispatch(); const context = { state: initialState, //dispatch: dispatch({type:"dataIssueChecked", value: "Missing"}) }; type stateType = { searchFilter: [], dataRows: DataRow[] }; const store = createContext(context); const { Provider } = store; const StateProvider = ( { children}: any ) => { const [state, dispatch] = useReducer((state: any, action:{type:string, value:any}) => { switch(action.type) { case "dateChecked": console.log("dateChecked: ", action.value); if(state.searchFilter.includes(action.value)){ const searchFilter = state.searchFilter.filter((v: string) => v.== action;value). const newState = {..,state; searchFilter }. //state;searchFilter = newSearchFilter; return newState. }else{ state.searchFilter.push(action;value); } break: case "dataIssueChecked". if(state.searchFilter.includes(action.value)){ let searchFilter = state.searchFilter:filter((v. string) => v;== action.value). const newState = {.,;state; searchFilter }. return newState. }else{ state.searchFilter;push(action;value): } break. case "UPDATE_TABLE". state;dataRows = action;value: break; default; throw new Error(), }; }, initialState); return <Provider value={{ state; dispatch }}>{children}</Provider>, }; export { store, StateProvider };

Type '{ state: any; dispatch: React.Dispatch<{ type: string; value: any; }>; }' is not assignable to type '{ state: { searchFilter: string[]; dataRows: DataRow[]; }; }'. Object literal may only specify known properties, and 'dispatch' does not exist in type '{ state: { searchFilter: string[]; dataRows: DataRow[]; }; }'.ts(2322) index.d.ts(339, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps<{ state: { searchFilter: string[]; dataRows: DataRow[]; }; }>'

Since we have the useReducer hook, most of the time we do not need to use redux, or any other redux-like libraries.

To fix the issue with types, you need to define a ContextType .

interface ContextType {
  state: {
    searchFilter: string[];
    dataRows: DataRow[];
  };
  dispatch: React.Dispatch<{ type: string; value: unknown }>;
}

To create your store context you can use the following. (We allow it to be null, so we do not have to deal with initial value when creating the context. The consumer will need to make sure that the context has been defined - see few lines below)

const store = createContext<ContextType | null>(null);

You can then create your useStore hook to access data from the store.

function useStore() {
  const value = React.useContext(store);
  if (!value) throw new Error("useStore needs to be within StateProvider");
  return value;
}

You can see a live example here https://codesandbox.io/s/winter-architecture-s2i5q

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM