使用 React.cloneElement 和 render prop 将 ref 传递给类组件

2024-02-03

我正在编写一个处理一些内部的组件state根据一个ref它的子级(例如与该子级的引用相关的鼠标事件)。
该组件正在使用render-prop传递相关部分state给它的孩子,并渲染孩子ref通过附加React.cloneElement util.

问题是当孩子是class组件,由于某种原因ref不可用,我找不到渲染它的方法,因为它是一个类型为的反应元素对象function(当然是在我克隆它之后)。

但如果孩子只是一个DOM节点像div例如,它正在按预期工作。

我的解决方法是检查孩子的类型,如果它是function我将用我自己的元素包装克隆的元素div,如果它只是一个 dom 节点,则按原样渲染。
然而,我不想用额外的东西包裹孩子div因为我不想添加不必要的DOM nodes.

这是一个基本的代码示例,为了简洁起见,删除了大部分代码:
父组件:

class Parent extends Component {

    attachRef = node => {
        this.ref = node;
    }

    render() {
        const { render } = this.props;
        const { someValue } = this.state;
        const Child = render(someValue);
        const WithRef = React.cloneElement(Child, {
            ref: this.attachRef
        });
        if (typeof WithRef.type === 'string') { // node element
            return WithRef;
        }
        else if (typeof WithRef.type === 'function') {
            // this is a react element object.. not sure how to render it
            // return ?
        } else {
            // need to find a way to render without a wrapping div
            return (
                <div ref={this.attachRef}>{Child}</div>
            );
        }
    }
}

用法:

class App extends Component {
    render() {
        return (
            <div>
                <Parent render={someValue => <div> {someValue}</div>} />
                <Parent render={someValue => <Menu someValue={someValue} />} />
            </div>
        );
    }
}

当我像第一个例子一样渲染常规 DOM 节点时,它工作得很好,当我尝试渲染Menu(这是一个class组件)它不能像上面提到的那样工作。


我有几乎相同的问题。
我选择使用查找DOM节点 https://reactjs.org/docs/react-dom.html#finddomnode from react-dom,你可以看到完整的解决方案在反应外部点击 https://github.com/sag1v/react-external-click/blob/master/src/components/ExternalClick.js.

尽管警告指出:

findDOMNode 是一个用于访问底层 DOM 节点的逃生舱口。 在大多数情况下,不鼓励使用此逃生舱口,因为它 穿透组件抽象。

findDOMNode 仅适用于已安装的组件(即, 已被放置在 DOM 中)。如果您尝试在组件上调用此方法 尚未安装(例如在 render() 中调用 findDOMNode() 在尚未创建的组件上)将出现异常 抛出。

findDOMNode 不能用于功能组件。

我认为这是应对这一特殊挑战的更好解决方案。
它让您对消费者“透明”,同时能够定位组件中的目标DOM.

好的,就在这里,抓住参考:

componentDidMount() {
    this.ref = findDOMNode(this);
    // some logic ...
}

这就是我在没有自己的包装器的情况下使用渲染函数的方式:

render() {
        const { children, render } = this.props;
        const { clickedOutside } = this.state;
        const renderingFunc = render || children;

        if (typeof renderingFunc === 'function') {
            return renderingFunc(clickedOutside);
        } else {
            return null
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 React.cloneElement 和 render prop 将 ref 传递给类组件 的相关文章

  • 由于 apollo-client 未定义,无法解构 GraphQL 查询?

    我正在寻找调试与错误消息相关的问题 未捕获的类型错误 无法解构 0 apollo client WEBPACK IMPORTED MODULE 4 useQuery 因为它未定义 Context 我正在为我的 React js 项目设置后端
  • Eslint errorring 导入没有扩展名的 jsx

    我正在尝试在 es6 中导入 jsx 文件而不需要 jsx 扩展名 import LoginErrorDialog from LoginErrorDialogView Not import LoginErrorDialog from Log
  • 如何在react-bootstrap中禁用表单提交的

    在下面的代码片段中 我有许多文本类型的输入表单 如果用户点击 我似乎会得到相同的合成事件 就像他们按下提交按钮一样 我想忽略作为表单提交 只允许一个人按下 提交 按钮 我删除了一些表单组以减少示例 在所有情况下 按钮或 ENTER 键 e
  • 使用 ApolloClient 从 useContext 挂钩导入一个简单变量

    我的反应相对较新 似乎无法导入client来自上下文的变量 我有一个名为 federation tsx 的文件 其中包含一些代码 我相信这应该是相关部分 const link createHttpLink uri process env U
  • 如何在执行新操作时取消先前操作的执行?

    我有一个动作创建器 它会进行昂贵的计算 并在每次用户输入内容时调度一个动作 基本上是实时更新 但是 如果用户输入多个内容 我不希望之前昂贵的计算完全运行 理想情况下 我希望能够取消执行先前的计算并只执行当前的计算 没有内置功能可以取消Pro
  • IE 中未定义“代理”

    我通过 React Node 构建了一个 Excel 插件Umi https umijs org 我们已经实施了我们的身份验证系统 身份验证在 Chrome 和 Safari 中有效 我刚刚意识到它在 IE11 中不能很好地工作 F12表明
  • 在复选框内映射复选框 ReactJS

    我有一个函数 一旦主复选框被选中 就会触发子复选框 并且所有这些复选框都是从 JSON 映射的 主复选框 最高级别 及其下面的所有子复选框 第二级别 都会在单击时显示 并且效果很好 我想要显示的是单击时主复选框 第三级别 的子复选框2 级项
  • SWC with JavaScript:如何处理 CSS 导入以及如何绝对导入?

    TL DR 如何告诉 SWC 编译 React 组件中导入的 CSS 文件 如何告诉 SWC 在测试和 React 组件中编译绝对导入 这是一个最小的可重现示例 https github com janhesters riteway swc
  • 如何从CDN注入外部JS到Jest单元测试?

    我有 npm 和 webpack 的反应应用程序 我正在尝试向其添加单元测试 我使用的是包含在我的index html 中的CDN 的jQuery 而不是使用节点模块 我在组件中使用 jQueryTest1我向其中添加了单元测试用例 现在
  • 具有多种布局的 React Router v4

    我想在我的公共布局中渲染一些路线 并在我的私人布局中渲染一些其他路线 有没有一种干净的方法可以做到这一点 显然不起作用的示例 但我希望大致解释我正在寻找的内容
  • React:在哪里扩展对象原型

    我使用创建了一个纯 React 应用程序创建反应应用程序 https github com facebookincubator create react app 我想延长String类并在一个或多个组件中使用它 例如 String prot
  • 内的 ref={register} 给了我一个 path.split 错误

    嗨 我正在尝试用 React 制作一个表单 当我输入 ref register inside
  • 将 useRef 挂钩传递给 ref 属性的正确方法

    我不确定如何更明确地提出这个问题 但它是关于值传递 and 引用传递反应中的情况 还有胡克斯 我正在使用 gsap 来制作 div 滑入和滑出的动画 这是其上下文 但我猜测 ref 的用途并不重要 因此 这工作得很好 尽管这是一种更典型的类
  • 在 React 应用程序中简单连接到 mongodb

    我使用 create react app 创建了简单的反应应用程序 这个应用程序包含表单 验证和引导程序 没有什么花哨的东西能像魅力一样发挥作用 我还注册了 mongo 以获得免费集群 以便我可以发送一些数据 所以我有这个网址 mongod
  • “react-infinite-scroll-component” 一次调用后停止工作(loadMore 只被调用一次)

    我使用react infinite scroll component库进行分页 但即使hasMore为true loadMore也会被调用一次
  • React 中的输入仅允许数字(antd 样式)

    我知道 type number 有效 但这不是我想要的 my HTML
  • 使用 Babel.js 将 ES6 箭头函数编译为 Es5

    在查看 Mozilla 文档上的 ES6 箭头函数文档时 我了解到箭头函数应用了严格模式的所有规则 除了在link https developer mozilla org en US docs Web JavaScript Referenc
  • 如何在react-native中获取Text组件的onPress值

    我是一名新的 React Native 开发人员 我想使用 onPress 获取 Text 组件的值并将其传递给函数
  • firebase :: 无法读取 null 的属性“props”

    你好 我正在尝试将react router与firebase一起使用 但它给了我这个错误 无法读取 null 的属性 props 这正是代码 我正在其中使用我的反应路由器 向下代码位于作为登录面板组件的组件上 else if this em
  • 在 React.js 中编辑丰富的数据结构

    我正在尝试为数据结构创建一个简单的基于网格的编辑器 但我在使用 React js 时遇到了一些概念问题 他们的文档对此没有太大帮助 所以我希望这里有人可以提供帮助 首先 将状态从外部组件传输到内部组件的正确方法是什么 是否有可能将内部组件中

随机推荐