简体   繁体   English

Function 包装防止 componentDidUpdate?

[英]Function wrapper preventing componentDidUpdate?

I have a component FancySpanComponent:我有一个组件 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>
        );
    }
}

which I place into a logger wrapper PropsLogger, and that wrapper is created though React.forwardRef() so my main container may play with what the span inside FancySpanComponent (I'm learning React and test whatever situation I can, so please don't judge ^^'):我将其放入记录器包装器 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} />);

And it works perfectly fine: when a props changes, everything is re-rendered and the old and new props are longed into the console.它工作得非常好:当一个道具发生变化时,一切都会重新渲染,新旧道具都渴望进入控制台。 But if I want to make that wrapper more flexible and work for any component, I have to wrap itself into a function so I can pass the child class name and create it in the logger render() function (that very example comes from the reactjs.org doc): But if I want to make that wrapper more flexible and work for any component, I have to wrap itself into a function so I can pass the child class name and create it in the logger render() function (that very example comes from the 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));

The problem, in that case, is that each time props change, I don't know why but my logger wrapper and its child are not technically updated: they are dismounted and remounted, thus logger componentDidUpdate() is never fired.在这种情况下,问题是每次道具更改时,我不知道为什么,但我的记录器包装器及其子级在技术上没有更新:它们被卸载并重新安装,因此记录器 componentDidUpdate() 永远不会被触发。 Do you have a clue why this is happening in the case of that function call?你知道为什么在 function 调用的情况下会发生这种情况吗?

Thank you very much in advance.非常感谢您提前。

Try this approach.试试这个方法。 The HoC approach you were trying seems incorrect.您尝试的 HoC 方法似乎不正确。

You have to return a class from inside the function.您必须从 function 内部返回 class。 So that it could be uses like a React Component.这样它就可以像 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} />
));

Then use it like this, create the spanRef yourself.然后像这样使用它,自己创建spanRef

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

Check this Code Sandbox for a workking example检查此代码沙箱以获取工作示例

The reason it's unmounting/remounting is that every time FancySpan renders, it's creating a brand new class.卸载/重新安装的原因是每次 FancySpan 渲染时,它都会创建一个全新的 class。 A new class means it's a new type of component, and the main way react decides whether to unmount is by whether the types are different.一个新的 class 表示它是一种新型组件,react 决定是否卸载的主要方式是根据类型是否不同。 The two types of components consist of identical code, but react doesn't know that.这两种类型的组件包含相同的代码,但 react 并不知道这一点。

So what you'll need to do is create the component only once.所以你需要做的是只创建一次组件。 That means you're going to have to create the component before you know what the values are for the props and ref, so they'll need to be passed in later:这意味着您必须先创建组件,然后才能知道 props 和 ref 的值是什么,因此稍后需要传入它们:

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

const Temp = propsLoggerWrapper(FancySpanComponent);

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

This code seems also to work fine (same as suggested but without the need of an intermédiate temporary object):此代码似乎也可以正常工作(与建议的相同,但不需要中间临时对象):

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

const FancySpan = propsLoggerWrapper(FancySpanComponent);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 this.props不是componentDidUpdate()中的函数 - this.props is not a function in the componentDidUpdate() 在 componentDidUpdate 或 handleSubmit 上使用 Formik setFieldValue(错误:不是函数) - Using Formik setFieldValue on componentDidUpdate or on handleSubmit (error: not a function) 等待功能响应,然后在componentDidUpdate中更改状态 - Wait for function response then change state in componentDidUpdate 如何在React的功能组件中制作与componentDidUpdate函数类似的函数? - How to make a similar function as componentDidUpdate function in a functional component in React? 在安装的酶测试中未调用componentDidUpdate中的道具功能 - Prop function in componentDidUpdate not being called in mounted enzyme test 确保在componentDidMount或componentDidUpdate中仅调用一次函数 - Make sure function is called only once, either in componentDidMount or componentDidUpdate 如何在触发componentDidUpdate 2次时触发一次setInterval函数 - How to make setInterval function triggered once while componentDidUpdate is fired 2 times 如何使用 Jest + Enzyme 测试 google maps 功能是否在 componentDidUpdate() 上运行? - How to test if google maps function runs on componentDidUpdate() with Jest + Enzyme? ReactJS-在componentDidMount()和componentDidUpdate()中调用时,有效函数不起作用 - ReactJS - valid function not working when called in componentDidMount() and componentDidUpdate() wrapper.find不是一个函数 - wrapper.find is not a function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM