【问题标题】:How to pass a setter hook to a child component and satisfy TypeScript如何将 setter 钩子传递给子组件并满足 TypeScript
【发布时间】:2020-11-06 07:32:18
【问题描述】:

我想将 setter hook (setValuesList) 从父组件 (App.tsx) 传递给子组件 (AddNumber.tsx)

我在父组件中定义了这样的钩子:

const [valuesList, setValuesList] = useState<number[]>([]);

我想像这样将钩子传递给子组件:

<AddNumber valuesList={valuesList} setValuesList={setValuesList} />

但是我得到一个 Typescript 错误:

(JSX attribute) AppProps.setValuesList: (num: number) => void
Type 'Dispatch<SetStateAction<number[]>>' is not assignable to type '(num: number) => void'.
  Types of parameters 'value' and 'num' are incompatible.
    Type 'number' is not assignable to type 'SetStateAction<number[]>'.ts(2322)
AddNumber.tsx(5, 3): The expected type comes from property 'setValuesList' which is declared here on type 'IntrinsicAttributes & AppProps'

在子组件中,我正在为这样的道具定义一个接口:

interface AppProps {
  valuesList: number[];
  setValuesList: (num: number) => void;
}

有人看到我在这里做错了吗?

我的存储库位于:https://github.com/acandael/number-list

感谢您的帮助,

安东尼

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    这是useState钩子的类型定义

    function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
    

    因此,如果您在调用 useState 时将类型 number[] 传递给状态值,则 setter 函数的类型将为 React.Dispatch&lt;SetStateAction&lt;number[]&gt;&gt;

    import { SetStateAction } from 'react';
    
    // this interface will satisfy if you want to pass setValuesList directly
    interface AppProps {
      valuesList: number[];
      setValuesList: React.Dispatch<SetStateAction<number[]>>;
     
      // setValuesList: (val: number[]) => void  will also satisfy, but it is
      // better to be explict and pass React.Dispatch<SetStateAction<number[]>>
    }
    

    如果你不想修改接口,你可以创建并传递另一个函数。

    // you don't need to modify the interface if you take this approach -
    // the interface already satisfies the type required in this case
    const updateValue = (num: number) => {
     setValuesList(prev => prev.concat(num))
    }
    
    <AddNumber valuesList={valuesList} setValuesList={updateValue} />
    

    【讨论】:

    • 感谢您的帮助@subashMahapatra 我将接口设置为: setValuesList: React.Dispatch>;但我收到此错误:找不到名称“SetStateAction”
    • import { SetStateAction } from react 或使用React.SetStateAction
    • 你可以用Dispatch做同样的事情,要么从'react'导入,要么使用React.Dispatch
    • 我导入了 { SetStateAction }。这似乎有效。但是,当我尝试像这样调用钩子时: props.setValuesList(number);我收到错误:“数字”类型的参数不可分配给“SetStateAction”类型的参数。
    • 感谢@subashMahapatra,这很有效。我会将您的回复标记为解决方案
    【解决方案2】:

    错误意味着您将错误的东西分配给错误的类型。 setValuesList 是可调用的,但属于 Dispatch&lt;SetStateAction&lt;number[]&gt;&gt; 类型,这与 (num: number) =&gt; void 明显不同。

    我看到了两种解决方法:

    • AppPropssetValueList的类型改成Dispatch&lt;SetStateAction&lt;number[]&gt;&gt;(还有作弊的any类型,但如果可以避免的话我不推荐)。
    • 您将 setValuesList 包装在一个函数中(应该看起来像 (num: number) =&gt; setValuesList(num)),它可以满足您的需求并尊重类型系统

    对于第二种解决方案,好的候选人也可能是useCallbackuseMemo,但我对它们还不够熟悉...但是查看文档可能会对您有所帮助。

    【讨论】:

    • 感谢@ShadowMitia 的帮助。我会尝试在 AppProps 中更改 setValueList 的类型,但是我应该将它更改为什么类型呢?
    • 你可以试试改成Dispatch&lt;SetStateAction&lt;number[]&gt;&gt;.
    • 我将其更改为 'setValuesList: Dispatch>' 但我收到此错误:找不到名称 'Dispatch' 我想我应该导入 'Dispatch'?
    • 是的,但你也可以使用 React.Dispatch,就像在 subashMahapatra 的回答中一样
    【解决方案3】:

    来自useState 的setter 函数是Dispatch&lt;SetStateAction&lt;number[]&gt;&gt; 类型

    如果你想让你的界面工作,你应该传递(num: number) =&gt; void函数类型:

    <AddNumber
      valuesList={valuesList}
      setValuesList={(num: number) => {
        setValuesList(num);
      }}
    />
    

    【讨论】:

      猜你喜欢
      • 2020-09-17
      • 1970-01-01
      • 2020-05-08
      • 1970-01-01
      • 2021-06-30
      • 2021-12-04
      • 2021-01-16
      • 1970-01-01
      • 2021-07-28
      相关资源
      最近更新 更多