在 React 中将 ref 从 child 传递到 parent 到另一个 child

Passing ref from child to parent to anothe child in React

我正在尝试从 child 中提取引用并使其在我的应用程序的其他地方可用。这是我的 parent 组件:

class App extends React.Component {

   setRef = (ref) => {
      this.mapReference = ref
      console.log(this.mapReference);
   }

   render () {
      return (
         <div className="App">
            <Map setRef={this.setRef} />
            <UIWindow mapRef={this.mapReference} />
         </div>
      )
   }
}

export default App;

并且引用来自 <Map /> 组件中的回调 setRef 函数,它看起来像这样:

class Map extends React.Component {


   componentDidMount(){
      this.props.setRef(this.refs.map.leafletElement)
   }

   render () {

      const { position, zoom } = this.props

      return(
         <LeafletMap
            className="sidebar-map" 
            center={position} zoom={zoom} id="mapId" 
            ref={"map"}
         >


         </LeafletMap>
      )
   }
}

我的 <App /> 中的 console.log 语句正确返回了我的引用,它是一个映射 object。所以我的引用被正确地从 child (<Map />) 传递到 parent (<App />),并且在那里可用。如您所见,我正在尝试将该引用传递回我的 <UIWindow /> 以在那里访问它。

class UIWindow extends React.Component {

   componentDidMount() {
      console.log(this.props.mapRef);
   }

   render () {
      return(
         <div className="UIWindow">
            <Header />
            <ControlLayer />
         </div>
      )
   }
}

export default UIWindow;

但在我的 UIWindow 中,this.props.mapRef 未定义 - 日志语句未定义。我不确定我在这里错过了什么。如果它在 parent 应用程序中定义,为什么它在 child 中未定义?这不是在兄弟姐妹之间传递引用的正确方法吗?

React 在 re-renders 时不知道 this.mapReference 是什么,因为变量与 class 的那个实例相关联。您可以声明状态并将其传递给 child:

class App extends React.Component {
   state = { mapReference: null }   

   setRef = ref => {
      this.setState({ mapReference: ref }, () =>
      console.log(this.state.mapReference)
     ); //Log once reference is updated
   };       

   render () {
      return (
         <div className="App">
            <Map setRef={this.setRef} />
            {this.state.mapReference && <UIWindow mapRef={this.state.mapReference} />}
         </div>
      )
   }
}

export default App;