First off, let me express that this is generally not the way to go about things in React land.
(首先,让我表示,这通常不是在React领域中解决问题的方法。)
Usually what you want to do is pass down functionality to children in props, and pass up notifications from children in events (or better yet: dispatch
).(通常,您要做的是将功能传递给props中的子代,并传递事件中子代的通知(或者更好的是: dispatch
)。)
But if you must expose an imperative method on a child component, you can use refs .
(但是,如果必须在子组件上公开命令式方法,则可以使用refs 。)
Remember this is an escape hatch and usually indicates a better design is available.(请记住,这是一个逃生舱口,通常表示可以使用更好的设计。)
Previously, refs were only supported for Class-based components.
(以前,仅基于类的组件才支持引用。)
const { forwardRef, useRef, useImperativeHandle } = React; // We need to wrap component in `forwardRef` in order to gain // access to the ref object that is assigned using the `ref` prop. // This ref is passed as the second parameter to the function component. const Child = forwardRef((props, ref) => { // The component instance will be extended // with whatever you return from the callback passed // as the second argument useImperativeHandle(ref, () => ({ getAlert() { alert("getAlert from Child"); } })); return <h1>Hi</h1>; }); const Parent = () => { // In order to gain access to the child component instance, // you need to assign it to a `ref`, so we call `useRef()` to get one const childRef = useRef(); return ( <div> <Child ref={childRef} /> <button onClick={() => childRef.current.getAlert()}>Click</button> </div> ); }; ReactDOM.render( <Parent />, document.getElementById('root') );
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <div id="root"></div>
Documentation for useImperativeHandle()
is here :
(useImperativeHandle()
文档在这里 :)
useImperativeHandle
customizes the instance value that is exposed to parent components when using ref
.
(useImperativeHandle
自定义使用ref
时公开给父组件的实例值。)
const { Component } = React; class Parent extends Component { constructor(props) { super(props); this.child = React.createRef(); } onClick = () => { this.child.current.getAlert(); }; render() { return ( <div> <Child ref={this.child} /> <button onClick={this.onClick}>Click</button> </div> ); } } class Child extends Component { getAlert() { alert('getAlert from Child'); } render() { return <h1>Hello</h1>; } } ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <div id="root"></div>
For historical purposes, here's the callback-based style you'd use with React versions before 16.3:
(出于历史目的,这是您在16.3之前的React版本中使用的基于回调的样式:)
const { Component } = React; const { render } = ReactDOM; class Parent extends Component { render() { return ( <div> <Child ref={instance => { this.child = instance; }} /> <button onClick={() => { this.child.getAlert(); }}>Click</button> </div> ); } } class Child extends Component { getAlert() { alert('clicked'); } render() { return ( <h1>Hello</h1> ); } } render( <Parent />, document.getElementById('app') );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…