Forwarding Refs
引用传递是把引用从组件传递到它的后代的方法.这种方法在高阶组件中特别有用.
接下来我们举一个利用高阶组件打印组件属性到控制台的例子:
function logProps(WrappedComponent) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return LogProps;
}
这个 “logProps”高阶组件把所有属性传递给它包装的组件,所以渲染后的结果将是一样的。例如,我们可以用这个高阶组件记录自身获得的属性,并且把属性传递到我们的”fancy button” 组件:
class FancyButton extends React.Component {
focus() {
// ...
}
// ...
}
// Rather than exporting FancyButton, we export LogProps.
// It will render a FancyButton though.
export default logProps(FancyButton);
上面的例子有个问题:refs属性不会被传递下去。因为ref
不是一个属性。就像key
,react用不一样的方式处理它们。
如果你在高阶组件上添加ref属性,ref属性只会指向最外层的容器组件,而不是被包装的组件。
这意味着我们想要ref关联到FancyButton
组件,但实际上ref被关联到到LogProps
组件:
import FancyButton from './FancyButton';
const ref = React.createRef();
// The FancyButton component we imported is the LogProps HOC.
// Even though the rendered output will be the same,
// Our ref will point to LogProps instead of the inner FancyButton component!
// This means we can't call e.g. ref.current.focus()
<FancyButton
label="Click Me"
handleClick={handleClick}
ref={ref}
/>;
幸运的是,我们可以通过使用React.forwardRef
API传递外层容器的refs到内部FancyButton
组件.
React.forwardRef
是入参为props
和ref
并且返回类型是React节点的函数。例如:
function logProps(Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// Assign the custom prop "forwardedRef" as a ref
return <Component ref={forwardedRef} {...rest} />;
}
}
// Note the second param "ref" provided by React.forwardRef.
// We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
// And it can then be attached to the Component.
function forwardRef(props, ref) {
return <LogProps {...props} forwardedRef={ref} />;
}
// These next lines are not necessary,
// But they do give the component a better display name in DevTools,
// e.g. "ForwardRef(logProps(MyComponent))"
const name = Component.displayName || Component.name;
forwardRef.displayName = `logProps(${name})`;
return React.forwardRef(forwardRef);
}