如何使用道具和状态注释反应功能组件?

时间:2021-03-30 08:56:11

标签: reactjs typescript react-native

我正在构建一个 React Native 应用程序。我有一个父组件和一个子组件。子组件有一个按钮,其事件处理程序位于父组件中。在事件处理程序结束时,我还必须更新子组件中的特定状态。所以出于这个原因,我在父组件中使用 useRef 钩子来创建子组件的引用。现在,事件处理函数看起来像这样

const handleJoin = async (community: TCommunity) => {
    // ..........
    childComponentRef.current.setIsDataManipulated(true);
    // ..........
};

但是我在 setIsDataManipulated 中看到一条红色波浪线,当我将鼠标悬停在它上面时,会出现以下错误

Property 'setIsDataManipulated' does not exist on type 'FC<TChildrenProps>'

这一定是因为 typescript 无法知道子组件具有我正在尝试更新的状态。现在,我只用 props 类型而不是 state 类型来注释子组件。我在网上查了一下,发现在使用基于类的组件时,可以传递第二个泛型类型,例如 React.Component<TProps, TState> 来注释 props 和 state。但是我如何使用 React.FC 这样做?

1 个答案:

答案 0 :(得分:3)

<块引用>

这一定是因为打字稿无法知道子组件具有我正在尝试更新的状态。

不,这是因为该元素没有具有该名称的公开方法/函数,原因如下:

  • ref 将引用 DOM 元素。
  • 但即使它引用了子组件实例,虽然该实例在其实现中可能具有 setIsDataManipulated 函数,但不会以任何方式向父组件公开。

这不是 TypeScript 的东西(尽管 TypeScript 很早就指出了这一点),childComponentRef.current 上实际上不存在该方法/函数。

如果你想让父组件控制子组件内的状态,不要在子组件中让它成为状态,而是让它成为一个道具。这就是 props:由它们提供给子组件的父组件控制的状态。如果子组件必须告诉父组件 prop 需要改变,让父组件传递给它一个 setter 来使用。

<块引用>

我在网上搜索发现,在使用基于类的组件时,我可以传递第二个泛型类型,如 React.Component<TProps, TState> 来注释 props 和 state。但是我如何使用 React.FC 这样做?

不,React.FC (React.FunctionComponent) 只有一个类型参数,用于道具。没有理由让它有状态的类型参数,因为它不会用于任何事情。使用 React.Component,状态类型参数决定了组件代码实例的 state 属性是什么,以便在 this.state 组件中使用 this.setStateclass 的代码可以进行类型检查。但是功能组件中的状态不是这样工作的。没有单一的状态对象。相反,在使用 useState 时,您可以直接定义每个状态成员的类型。

下面是一个例子:一个 class 组件有一个 prop 和两个 state 项,而 function 组件有相同的 prop 和 state 项:

class ClassExample extends React.Component<{prop1: string}, {state1: number; state2: string | null}> {
    constructor(props: {prop1: string}) {
        super(props);
        this.state = {
            state1: 42,     // If these weren't here, TypeScript
            state2: null,   // would warn they were missing, thanks
                            // to the state type argument
        };
    }
    // ...
}

const FunctionExample: React.FC<{prop1: string}> = ({prop1}) => {
    const [state1, setB] = useState(42); // TypeScript infers `number` for type
    const [state2, setC] = useState<string | null>(null); // Explicit so TypeScript knows it's `string | null`

    // ...
};