如果组件是使用 React.Fragment 有多个元素,要指明实际是哪元素的 ref
const Foo = forwardRef((props, ref) => {
return (
<>
<h1 ref={ref}></h1>
<input type="input" />
</>
)
})
如果多个元素都的一部分信息都要在 ref 中,那么可以使用 useImperativeHandle 来封装 ref 再用 forwardRef 传回去
const Foo = forwardRef((props, ref) => {
const h1Ref = useRef();
const inputRef = useRef();
useImperativeHanlde(ref, ()=> {
h1: h1Ref.current,
focus: inputRef.current.focus
}, []);
return (
<>
<h1 ref={h1Ref}></h1>
<input type="input" ref={inputRef}/>
</>
)
})
函数组件不能给 ref,会报错
const Foo = props => {
const inputRef = useRef();
onClick = () => {
inputRef.current.focus();
}
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={onClick}>聚集</button>
</div>
)
}
const App = props => {
const FooRef = createRef();
const onClick = () => {
FooRef.current.onClick();
}
// Foo 是函数组件指定 ref 会报错
return (
<div>
<Foo ref={FooRef}/>
<button onClick={onClick}>父组件</button>
</div>
)
}
这时会可用 forwardRef 来转发 Ref,使用 forwardRef 对函数组件进行包裹
const Foo = forwardRef(
(props, inputRef) => {
onClick = () => {
inputRef.current.focus();
}
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={onClick}>聚集</button>
</div>
)
}
)
const App = props => {
const FooRef = createRef();
const onClick = () => {
FooRef.current.focus(); // 这里直接拿到子组件的 DOM
}
return (
<div>
<Foo ref={FooRef}/>
<button onClick={onClick}>父组件</button>
</div>
)
}