簡體   English   中英

如何從 React 16 門戶獲取引用?

[英]How to get ref from a React 16 portal?

有沒有辦法從 React 16 門戶獲取ref 我嘗試了以下方法,但似乎不起作用:

const Tooltip = props => (
  ReactDOM.createPortal(
    <div>{props.children}</div>,
    // A DOM element
    document.body
  )
);

class Info extends React.Component {
   render() {
      return (
        <Tooltip 
          ref={ el => this.tooltip = el }
        >
          My content
        </Tooltip>
      ); 
   }

   componentDidMount() {
      console.log(this.tooltip); // undefined
   }
}

我需要ref才能動態計算元素的最終位置!

https://codepen.io/anon/pen/QqmBpB

ReactDOM.createPortal返回一個ReactPortal實例,它是一個有效的ReactNode但不是一個有效的 DOM 元素。 同時createPortal將尊重組件上下文。 所以我將函數調用移到了 render 方法中,它解決了這個問題。

class Info extends React.Component {
  render() {
    // I moved the portal creation to be here
    return ReactDOM.createPortal(
       // A valid DOM node!!
       <div ref={ el => this.tooltip = el }>{props.children}</div>,
       // A DOM element
       document.body
    ); 
  }

  componentDidMount() {
     console.log(this.tooltip); // HTMLDivElement
  }
}

如果你想用鈎子來做,你也可以這樣做

import { createPortal } from 'react-dom'
import React, { useRef } from 'react'

const Portal = ({ children }) => {
  const portal = useRef(document.createElement('div'))
  return createPortal(children, portal.current)
}

此外,在您的確切示例中,您需要使用forwardRef因為沒有它您無法將refs傳遞給孩子。

const Tooltip = forwardRef((props, ref) => (
  createPortal(
    <div ref={ref}>{props.children}</div>,
    // A DOM element
    document.body
  )
));

const Info = () => {
  const ref = useRef()
  return (
    <Tooltip ref={ref}>
      My content
    </Tooltip>
  )
}

最后一點沒有經過測試,但我很確定它會起作用。

您需要在 App 組件中使用this.tooltip.props.children並在 Tooltip 組件中使用以下代碼:

const appRoot = document.getElementById('app-root');
const tooltipRoot = document.getElementById('tooltip-root');

class Tooltip extends Component {
  constructor(props) {
    super(props);
    // Create a div that we'll render the Tooltip into
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // Append the element into the DOM on mount.
    tooltipRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    // Remove the element from the DOM when we unmount
    tooltipRoot.removeChild(this.el);
  }

  render() {
    // Use a portal to render the children into the element
    return ReactDOM.createPortal(
      // Any valid React child: JSX, strings, arrays, etc.
      this.props.children,
      // A DOM element
      this.el,
    );
  }
}

class App extends React.Component {
      componentDidMount() {
        console.log(this.tooltip.props.children);
      }
      render() {
        return (
          <div>
            <Tooltip ref={ el => this.tooltip = el }>
              My content
            </Tooltip>
          </div>
        );
      }
    }

ReactDOM.render(<App />, appRoot);

工作演示https://codepen.io/jorgemcdev/pen/aLYRVQ ,基於 Dan Abramov 代碼示例https://codepen.io/gaearon/pen/jGBWpE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM