简体   繁体   English

在 typescript 中将 useState 作为道具传递

[英]Passing useState as props in typescript

Say I have a parent component with two child components:假设我有一个包含两个子组件的父组件:

const Parent = () => {
   const [myVar, setmyVar] = useState(false)

   return (
     <>
       <MyChildComponent1 myVar={myVar} setMyVar={setMyVar} \> 
       <MyChildComponent2 myVar={myVar} \>
     </>
   )
}

Now how would I go about setting the type correctly in MyChildComponent2 ?现在我 go 如何在MyChildComponent2中正确设置类型?

This is what I've come up with so far:到目前为止,这是我想出的:

const MyChildComponent1 = (
  {myVar, setMyVar}: 
  {myVar: boolean, setMyVar: (value: boolean) => void}) = (...)

Is the type for setMyvar correct? setMyvar的类型是否正确? Or should it be something else?或者它应该是别的什么?

The type that would match the function returned from invoking useState would be:与调用useState返回的函数相匹配的类型将是:

setMyVar: (value: boolean | ((prevVar: boolean) => boolean)) => void;

If we look at the type definition file from DefinitelyTyped [1], we can see that the second type in the return type is a dispatch:如果我们查看来自DefinitelyTyped类型 [1] 的类型定义文件,我们可以看到返回类型中的第二个类型是调度:

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

Thus the generic type provided is passed through to SetStateAction<S> , which is defined as:因此,提供的泛型类型传递给SetStateAction<S> ,其定义为:

type SetStateAction<S> = S | ((prevState: S) => S);

So essentially, an interface for your component would be the following:因此,基本上,您的组件的接口如下所示:

interface IProps {
  myVar: boolean;
  setMyVar?: (value: boolean | (prevVar: boolean) => boolean) => void;
}

As @Retsam said, it's best to use React's exported types:正如@Retsam 所说,最好使用 React 的导出类型:

import { Dispatch, SetStateAction } from "react";

interface IProps {
  myVar: boolean;
  setMyVar?: Dispatch<SetStateAction<boolean>>;
}

References: [1] https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L845参考文献:[1] https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L845

Dispatch & SetStateAction types调度和 SetStateAction 类型

As @Retsam mentioned, you can also import and use the types Dispatch and SetStateAction from React:正如@Retsam 提到的,您还可以从 React 导入和使用DispatchSetStateAction类型:

import React, { Dispatch, SetStateAction } from 'react';

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatch<SetStateAction<boolean>>
) => {...};

Bonus奖金

When I find myself frequently using this, I create a type alias to help with readability当我发现自己经常使用它时,我会创建一个类型别名来帮助提高可读性

import React, { Dispatch, SetStateAction } from 'react';

type Dispatcher<S> = Dispatch<SetStateAction<S>>;

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatcher<boolean>,
) => {...};

hope this helps.希望这可以帮助。

Adding onto @fiz's comment, his code of block was slightly not working for me:添加到@fiz 的评论中,他的代码块对我来说有点不起作用:

import React, { Dispatch, SetStateAction } from 'react';

const MyChildComponent1 = (
  myVar: boolean,
  setMyVar: Dispatch<SetStateAction<<boolean>>
) => {...};

I had to set setMyVar: Dispatch<SetStateAction<boolean>> (there was one too many brackets)我必须设置setMyVar: Dispatch<SetStateAction<boolean>> (括号太多了)

It can also be done like this using Interface and React components.也可以使用 Interface 和 React 组件来完成。

MainComponent.tsx主要组件.tsx

Value assignment of the useState component defined in Main is done in the child component. Main中定义的useState组件的赋值是在子组件中完成的。 When this field is triggered, the code in useEffect will run.当该字段被触发时,useEffect 中的代码将运行。

import React, { useEffect } from 'react';
import Login from './views/Login/index';

const App: React.FunctionComponent = () => {
    const [isAuthenticated, setAuthenticatedStatus] = React.useState(false);

    useEffect(() => {
        if (isAuthenticated)
            window.location.href = "<redirect url>";
    }, [isAuthenticated]);

    return (<Login setLoginStatus={setAuthenticatedStatus} />)
};

export default App;

ChildComponent.tsx ChildComponent.tsx

import { Dispatch, SetStateAction, FunctionComponent } from 'react';
import authService from '../../apiServices/authService';

interface IProps {
   setLoginStatus: Dispatch<SetStateAction<boolean>>;
}

const Login: FunctionComponent<IProps> = (props: IProps) => {

   const login = async (username: string, password: string) => {
      const response = await authService.authenticateUser(username, password);

      if (response && response.statusCode == 200 && response.result.accessToken) {
         props.setLoginStatus(true);
      }
      else {
         // ...
      }
   };


   return (
      <>
         ...
      </>
   );
};

export default Login;

MyChildComponent1.tsx MyChildComponent1.tsx
set type Props like this:像这样设置类型道具:

import React from 'react'从“反应”导入反应

type Props = {类型道具 = {
myVar:boolean;我的变量:boolean;
setmyVar: React.Dispatch<React.SetStateAction <boolean> >; setmyVar: React.Dispatch<React.SetStateAction <boolean> >;
} }
const MyChildComponent = ({myVar, setmyVar}: Props) => { const MyChildComponent = ({myVar, setmyVar}: Props) => {

... YOUR CODE... ...您的代码...


} }

I found the other answers slightly confusing, so here's what worked for me:我发现其他答案有点令人困惑,所以这对我有用:

Instantiate useState() in parent.ts:在 parent.ts 中实例化 useState():

const [someState, setSomeState] = useState<stateType>(initialState)

Pass in setSomeState() to child.ts:将 setSomeState() 传递给 child.ts:

<Child
    setSomeState={setSomeState}
/>

Make sure to only pass the name without the ()确保只传递没有 () 的名称

In child.ts set Props like so:在 child.ts 中设置 Props 如下:

import Dispatch from 'react'

interface Props {setSomeState: Dispatch<stateType>}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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