首页 > 解决方案 > 输入'{状态:任何;调度:React.Dispatch<{ 类型:字符串;值:任何;}>; }' 不可分配给类型

问题描述

我正在构建一个 UI,左侧有一些复选框,右侧有一个数据表,还有放置区框,我希望每次放置一个新文件时都能够维护表数据,并根据复选框选择过滤表中的数据,无论如何,我构建了大部分内容,并且能够将选择控件传递给主要组件以过滤/排序数据,后来我尝试添加redux维护应用程序的状态,但它不能顺利使用钩子,并且它一直抱怨从函数组件体外部调用钩子,尽管它们不是。我得出的结论是,它们不能很好地协同工作,并切换了使用contextredux一起维护状态并构建这个组件,但是我遇到了编译问题,自从我使用 react/hooks/redux 已经 2 年了,我觉得过去 2 年事情发生了变化。

**) 我关于 redux 和 hooks 冲突的结论对吗?如果没有,你能不能给它一些亮点?

下面是代码和错误,有问题的行是 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 };

输入'{状态:任何;调度:React.Dispatch<{ 类型:字符串;值:任何;}>; }' 不可分配给类型 '{ state: { searchFilter: string[]; 数据行:数据行[];}; }'。对象字面量只能指定已知属性,而 'dispatch' 不存在于类型 '{ state: { searchFilter: string[]; 数据行:数据行[];}; }'.ts(2322) index.d.ts(339, 9): 预期的类型来自属性'value',它在类型'IntrinsicAttributes & ProviderProps<{ state: { searchFilter: string[]; 数据行:数据行[];}; }>'

标签: javascriptreactjstypescriptredux

解决方案


由于我们有useReducer钩子,大多数时候我们不需要使用 redux 或任何其他类似 redux 的库。

要解决类型问题,您需要定义一个ContextType.

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

要创建您的商店上下文,您可以使用以下内容。(我们允许它为空,因此我们在创建上下文时不必处理初始值。消费者需要确保已定义上下文 - 请参见下面的几行)

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

然后,您可以创建useStore挂钩以访问存储中的数据。

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

你可以在这里看到一个活生生的例子https://codesandbox.io/s/winter-architecture-s2i5q


推荐阅读