【问题标题】:Is there a way to access a function returned by a React component through a parent HTMLDivElement?有没有办法通过父 HTMLDivElement 访问 React 组件返回的函数?
【发布时间】:2020-08-12 18:36:12
【问题描述】:

我有一个自定义的React 组件Foo,它包含另一个自定义组件SubFoo,它又包含一个内联库组件<Bar/>。从Foo 我需要访问一个函数, BarFunc,由<Bar/>返回。不幸的是,<Bar/> 未设置为与refs 一起使用 - 当我尝试将ref 传递给<Bar/>(使用Foo 转发到SubFoo 使用React.forwardRef())时,我得到@ 987654336@.

但是,在SubFoo 中有一个div<Bar/> 的父级,如果我将ref 传递给这个div,我会得到一个HTMLDivElement

鉴于我的HTMLDivElement,有什么方法可以执行BarFunc

【问题讨论】:

  • 遗漏了-HTMLDivElement 来自div 返回的ref 的第一个孩子
  • 您是说您有一个返回 function 的组件,还是您是说您有一个功能组件 Bar 不能使用 ref 来返回一个带有您想要访问的BarFunc API 的子组件?如果是前者,SubFoo 使用的函数如何(因为据我了解,如果 () => "Magic" 从组件作为函数返回,React 不知道如何渲染它)?
  • 你能给我们一些代码吗?
  • 我有一个返回一些 HTML 的组件以及一个 functionBar 的文档实际上将此函数称为“返回值”(该文档本质上只是props 和返回值的列表)。 function 不被 SubFoo 使用,div + 组件只是由 SubFoo 返回并带有某些 propsFoo 发生某个事件时我需要调用它
  • @7iiBob 这是一个小提琴。实际上,除了onClick 之外,还有更复杂的事情发生,但包括在内只会让jsfiddle.net/h4fucgsq 变得更混乱@

标签: javascript reactjs


【解决方案1】:

有多种方法可以完成您想做的事情:

  1. 修改SubFoo 以代理Bar 通过其render-prop 提供的行为。然后Foo 可以引用SubFoo 并间接调用行为:

    class SubFoo extends React.Component {
      barBehavior = () => this.barBehaviorFunc?.()
    
      renderProp = barApi => {
        this.barBehaviorFunc = barApi.barBehavior;
        return <div><other components={here} /></div>;
      }
    
      render() {
        return <Bar>{this.renderProp}</Bar>;
      }
    }
    
    class Foo extends React.Component {
      onClick() { this.ref?.barBehavior();
      render() {
        return <SubFoo ref={r => this.ref = r} />
      }
    }
    
  2. 使用React.Context API 向上公开此行为(如果您在FooSubFoo 之间有不可修改的代码)。

    const BarBehaviorContext = React.createContext(() => {});
    
    class Foo extends React.Component {
      setBarBehavior = barBehavior => this.barBehavior = barBehavior;
      render() { return <BarBehaviorContext.Provider value={this.setBarBehavior}><SubFoo /></BarBehaviorContext.Provider>;
    }
    
    class SubFoo extends React.Component {
      render() {
        return <BarBehaviorContext.Consumer>{setter => <Bar>{api => (setter(api.barBehavior), <div>...</div>)}</Bar>}</BarBehaviorContext.Consumer>
      }
    }
    

【讨论】:

  • 感谢@seanvieira,解决方案 2 似乎对我有用!
  • 抱歉,最后一条评论有误。解决方案 1 对我有用。但是我还需要使用我找到的here 的部分答案,特别是关于React.useImperativeHandle的部分
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多