gpt4 book ai didi

javascript - 将 ref 与 React.createElement 一起使用

转载 作者:行者123 更新时间:2023-12-02 16:16:29 30 4
gpt4 key购买 nike

我有一个可重用的标题组件,它允许我传递 tag prop,创建任何类型的标题(h1、h2、h3 等)。这是该组件:

heading.tsx

import React, { ReactNode } from 'react';

import s from './Heading.scss';

interface HeadingProps {
tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
children: ReactNode;
className?: string;
}

export const Heading = ({ tag, children, className }: HeadingProps) => {
const Tag = ({ ...props }: React.HTMLAttributes<HTMLHeadingElement>) =>
React.createElement(tag, props, children);

return <Tag className={s(s.heading, className)}>{children}</Tag>;
};

但是,我遇到了一个用例,我希望能够拥有一个 ref , 使用 useRef() Hook ,在 Tag 上,这样我就可以访问该元素并使用 GSAP 制作动画。但是,我不知道如何使用 createElement 来做到这一点。 .

我尝试通过添加 ref 来做到这一点直接到 Tag组件,并将其添加到 Tag像这样的 Prop :

import React, { ReactNode, useRef } from 'react';

import s from './Heading.scss';

interface HeadingProps {
tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
children: ReactNode;
className?: string;
}

export const Heading = ({ tag, children, className }: HeadingProps) => {
const headingRef = useRef(null);
const Tag = ({ ...props }: React.HTMLAttributes<HTMLHeadingElement>) =>
React.createElement(tag, props, children, {ref: headingRef});

return <Tag className={s(s.heading, className)} ref={headingRef}>{children}</Tag>;
};

我收到错误 Property 'ref' does not exist on type 'IntrinsicAttributes & HTMLAttributes<HTMLHeadingElement>'.

我做错了什么,我怎样才能安全地添加 ref到组件?

谢谢。

最佳答案

使用对象传播将ref添加到props:

const { useRef, useEffect } = React;

const Heading = ({ tag, children, className }) => {
const headingRef = useRef(null);
const Tag = (props) => React.createElement(tag, {ref: headingRef, ...props }, children);

useEffect(() => { console.log(headingRef); }, []); // demo - use the ref

return <Tag>{children}</Tag>;
};

ReactDOM.render(
<div>
<Heading tag="h1">h1</Heading>
<Heading tag="h2">h2</Heading>
<Heading tag="h3">h3</Heading>
</div>,
root
);
.as-console-wrapper { max-height: 100% !important; top: 0; left: 50% !important; }
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

但是,在另一个组件内创建一个组件意味着该组件将在每次渲染时重新创建。您可以使用 useMemo() 来避免这种情况。然而,一个更简单的选择是将 tag 本身呈现为 JSX:

const { useRef, useEffect } = React;

const Heading = ({ tag: Tag, children, className }) => {
const headingRef = useRef(null);

useEffect(() => { console.log(headingRef); }, []); // demo - use the ref

return <Tag className={className} ref={headingRef}>{children}</Tag>;
};

ReactDOM.render(
<div>
<Heading tag="h1">h1</Heading>
<Heading tag="h2">h2</Heading>
<Heading tag="h3">h3</Heading>
</div>,
root
);
.as-console-wrapper { max-height: 100% !important; top: 0; left: 50% !important; }
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

关于javascript - 将 ref 与 React.createElement 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66549727/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com