操作
2023年05月10日
一、跨层级获取
需求: 有组件Parent
,Parent
组件中嵌套Child
组件,Child
嵌套组件GrandChild
组件,这时,Parent
组件想要获取GrandChild
中的某个元素,实现如下
方案: 通过 React.forwardRef
实现跨层级获取
实现:
import React, { useRef, forwardRef, useEffect } from "react";
import ReactDOM from "react-dom";
function GrandChild(props) {
const { forwardRef } = props;
return (
<div>
<div ref={forwardRef}>GrandChild 组件中的关键元素,Parent 组件想要获取</div>
</div>
);
}
function Child(props) {
const { forwardRef } = props;
return (
<div>
<h3>孩子</h3>
<GrandChild forwardRef={refData} />
</div>
);
}
const NewChild = forwardRef((props, ref) => <Child forwardRef={ref} {...props} />);
function Parent() {
const parent = useRef(null);
useEffect(() => {
console.log(parent);
});
return (
<div>
<h3>父亲</h3>
<NewChild ref={parent} />
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById("root"));
二、合并转发 Ref
需求: 有组件Parent
,Parent
组件中嵌套Child
组件,Child
组件中嵌套GrandChild
组件,Parent
组件想要获取Child
组件中的多个元素,实现如下
方案: 通过 React.forwardRef
实现合并转发 Ref
实现
import React, { useRef, forwardRef, useEffect } from "react";
import ReactDOM from "react-dom";
function GrandChild(props) {
const { forwardRef } = props;
return (
<div ref={forwardRef}>
<div>孙子</div>
</div>
);
}
function Child(props) {
const { forwardRef } = props;
const btn = useRef(null);
const grandChild = useRef(null);
useEffect(() => {
forwardRef.current = {
btn,
grandChild,
};
});
return (
<div>
<h3>孩子</h3>
<button ref={btn}>按钮</button>
<GrandChild forwardRef={grandChild} />
</div>
);
}
const NewChild = forwardRef((props, ref) => <Child forwardRef={ref} {...props} />);
function Parent() {
const ref = useRef(null);
useEffect(() => {
console.log(ref);
});
return (
<div>
<h3>父亲</h3>
<NewChild ref={ref} />
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById("root"));
三、高阶组件转发
背景: 如果通过高阶组件包裹一个原始类组件,就会产生一个问题,如果高阶组件 HOC
没有处理 ref
,那么由于高阶组件本身会返回一个新组件,所以当使用 HOC
包装后组件的时候,标记的 ref
会指向 HOC
返回的组件,而并不是 HOC
包裹的原始类组件
解决: 为了解决这个问题,forwardRef
可以对 HOC
做一层处理
实现:
import React, { useRef, forwardRef, useEffect } from "react";
import ReactDOM from "react-dom";
function HOC(Component) {
class Wrap extends React.Component {
render() {
const { forwardRef, ...otherProps } = this.props;
return <Component ref={forwardRef} {...otherProps} />;
}
}
return React.forwardRef((props, ref) => (
<Wrap forwardRef={ref} {...props}></Wrap>
));
}
class Index extends React.Component {
render() {
return <div>Index 组件</div>;
}
}
const NewIndex = HOC(Index);
function App() {
const ref = useRef(null);
useEffect(() => {
console.log(ref);
});
return (
<div>
<NewIndex ref={ref} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));