首页 > 解决方案 > 防止componentDidUpdate的函数包装器?

问题描述

我有一个组件 FancySpanComponent:

class FancySpanComponent extends React.Component {
    render() {
        return (
            <span ref={this.props.innerRef} className={this.props.className }>
                <div style={{ textAlign: "center" }}>rand: {this.props.randomData}</div>
            </span>
        );
    }
}

我将其放入记录器包装器 PropsLogger 中,并且该包装器是通过 React.forwardRef() 创建的,因此我的主容器可以使用 FancySpanComponent 中的跨度(我正在学习 React 并测试我可以测试的任何情况,所以请不要判断^^'):

class PropsLogger extends React.Component {
    componentDidMount() {
        console.log("(Logger) mounting");
    }
    componentDidUpdate(prevProps) {
        console.log("(Logger) Previous:", prevProps);
        console.log("(Logger) New:", this.props);
    }
    render() { return <FancySpanComponent innerRef={this.props.innerRef} {...this.props} />; }
}
const FancySpan = React.forwardRef((props, ref) => <PropsLogger innerRef={ref} {...props} />);

它工作得非常好:当一个道具发生变化时,一切都会重新渲染,新旧道具都渴望进入控制台。但是,如果我想让该包装器更灵活并适用于任何组件,我必须将自己包装到一个函数中,以便我可以传递子类名称并在记录器的 render() 函数中创建它(这个例子来自 reactjs .org 文档):

function propsLoggerWrapper(ClassToLog, props, ref) {
    class PropsLogger extends React.Component {
        componentDidMount() {...}
        componentDidUpdate(prevProps) {...}
        render() { return <ClassToLog innerRef={ref} {...props} />; }
    }

    return <PropsLogger />;
};
const FancySpan = React.forwardRef((props, ref) => propsLoggerWrapper(FancySpanComponent, props, ref));

在这种情况下,问题是每次道具更改时,我不知道为什么,但我的记录器包装器及其子级在技术上没有更新:它们被卸载并重新安装,因此记录器 componentDidUpdate() 永远不会被触发。您是否知道为什么在该函数调用的情况下会发生这种情况?

非常感谢您提前。

标签: reactjs

解决方案


试试这个方法。您尝试的 HoC 方法似乎不正确。

您必须从函数内部返回一个类。这样它就可以像 React 组件一样使用。

function propsLoggerWrapper(ClassToLog) {
    return class extends React.Component {
    componentDidMount() {}
    componentDidUpdate(prevProps) {}
    render() {
        return <ClassToLog {...this.props} ref={this.props.innerRef} />;
    }
};

const LoggedSpan = propsLoggerWrapper(Span);

const LoggedSpanWithRef = React.forwardRef((props, ref) => (
    <LoggedSpan innerRef={ref} {...props} />
));

然后像这样使用它,创建spanRef自己。

<LoggedSpanWithRef ref={this.spanRef} someprop={1} />

检查此代码沙箱以获取工作示例


推荐阅读