我如何在 reactjs + typescript (钩子)中使用 useRef 将子状态值传递给父级

Posted

技术标签:

【中文标题】我如何在 reactjs + typescript (钩子)中使用 useRef 将子状态值传递给父级【英文标题】:how can i get child state value to parent using useRef in reactjs + typescript (hooks) 【发布时间】:2020-12-30 01:35:10 【问题描述】:

我是 Typescript 的新手。我需要在单击按钮时使用 ref 将子状态值传递给父级以更新 reducer 值。

我尝试将ref 传递给孩子,但我收到类似以下的错误:

类型'值:字符串; onChange: 调度;参考: MutableRefObject; ' 不能分配给类型'IntrinsicAttributes & Props & children?: ReactNode; '。

类型'IntrinsicAttributes & Props & children?: ReactNode; 上不存在属性'ref' '.ts(2322)

父组件

import React, from "react";
import styled from "styled-components";
import 
    Page,
    Welcome,
    ErrorBoundary
 from "components";
const ParentDiv = styled.div`
            margin: 0 410px 30px 15px;
            `;

export const CreateEvent = (props: any) => 

    return (
        <Page title='Dashboard'>
            <ErrorBoundary>
                (() => 
                    switch (activeEventStage?.step) 
                        case 1:
                            return (
                                <ErrorBoundary>
                                    <Welcome />
                                </ErrorBoundary>
                            );
                        default:
                            return null;
                    
                )()
            </ErrorBoundary>
        </Page>
    );
;
export default withRouter(CreateEvent);

子组件

import React,  useState  from "react";
import  Row, Col  from "react-bootstrap";

export const Welcome = () => 
    const  t  = useTranslation();
    const [state, setState] = useState(
        welBannerTagline: "",
        welHeroTitle: "",
    );

    return (
        <CreateEventFormContainer
            title=t("event.create.title")
            subTitile=t("welcome.subTitle")
        >
            <>
                <Row>
                    <Col lg='6'>
                        <DropZoneInputField
                            titleName=t("welcome.bgImage.title")
                            onSelectedFiles=onDropFiles
                            imageType='bgImage'
                            value=state.welBgFilename
                        />
                    </Col>
                    <Col lg='6'>
                        <DropZoneInputField
                            titleName=t("welcome.banner.title")
                            onSelectedFiles=onDropFiles
                            imageType='bannerImage'
                            value=state.welBannerFilname
                        />
                    </Col>
                </Row>
            </>
        </CreateEventFormContainer>
    );
;
export default Welcome;

【问题讨论】:

你在哪里使用 useRef?我在上面的代码中没有看到它 我已经删除了,因为它破坏了我的工作,我只需要在钩子中使用 typescript 的解决方案来获取子状态值 【参考方案1】:

您收到该错误是因为 Welcome 并非旨在接受 ref 属性。

ref 是 React 中的保留属性名称,因此为了将属性 ref 传递给子组件,子组件必须使用 React.forwardRef 来接受 ref 属性。

您可以使用任何其他道具名称直接传递 ref 对象,例如myRef。在这种情况下,您不需要使用forwardRef,但您确实需要确保孩子的道具接受道具myRef,这是一个参考。

ref 本身的类型取决于它最终附加到 DOM 的位置。可能是htmlButtonElement

interface WelcomeProps 
    myRef: React.MutableRefObject<HTMLButtonElement | null>;


export const Welcome = (myRef: WelcomeProps) => 
...
export const CreateEvent = (props: RouteComponentProps) => 
    const refObject = React.useRef<HTMLButtonElement | null>(null);
    return (
...
       <Welcome myRef=refObject/>
...

这允许您与 DOM 进行交互。但这似乎不是您真正想要做的。

我需要在单击按钮时使用 ref 将子状态值传递给父级以更新 reducer 值。

只需传递一个回调!状态是否应该存储在孩子中,或者你可以lift it up给父母吗?

interface CallbackValue 
    // what properties does the callback want to receive?
    welBannerTagline: string;
    welHeroTitle: string;


interface WelcomeProps 
    myCallback: (value: CallbackValue) => void;


export const Welcome = (myCallback: WelcomeProps) => 
    const [state, setState] = useState(
        welBannerTagline: "",
        welHeroTitle: "",
    );

    const handleEvent = () => 
        myCallback(state);
    
...
export const CreateEvent = (props: RouteComponentProps) => 
    return (
...
       <Welcome myCallback=(value) => 
           // do something here with the value
        />
...

【讨论】:

【参考方案2】:

一个更简单的方法是使用 React 内置的 useRef 钩子和保留的 ref 属性。它仅适用于可变对象,因此您不必担心自己输入。

import  useRef  from "react";

export const CreateEvent = (props: any) => 

    const welcomeRef = useRef();

    return (
        <Page title='Dashboard'>
            <ErrorBoundary>
                (() => 
                    switch (activeEventStage?.step) 
                        case 1:
                            return (
                                <ErrorBoundary>
                                    <Welcome ref=welcomeRef />
                                </ErrorBoundary>
                            );
                        default:
                            return null;
                    
                )()
            </ErrorBoundary>
        </Page>
    );
;
export default withRouter(CreateEvent);

【讨论】:

以上是关于我如何在 reactjs + typescript (钩子)中使用 useRef 将子状态值传递给父级的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ReactJS Typescript 中 2 分钟后自动发生 onclick

ReactJs 和 Typescript,使用 TSX 时如何更改对象内变量的状态

Typescript & ReactJS 如何动态设置状态

typesafe 使用 reactjs 和 typescript 选择 onChange 事件

如何在 reactJS 中编写一个惰性加载器(带有示例)

如何学习用Typescript写Reactjs?