我想在React应用程序的给定生命周期方法上添加一些行为,而不必在每个方法中定义它?
我来自Java世界,一直试图在每个反应组件的生命周期方法中使用HOC进行打印/控制台,类似于Spring/Java中的AOP概念,或者你可以说生命周期方法的通用交叉,如componentWillUnmount、componentDidMount、componentWillMount。。。我想控制台组件名称和生命周期方法名称。
示例
组件B组件WillMount称为
组件A组件WillMount称为
组件B组件DidMountcalled。。。
我曾试图使用HOC纠正我的错误,但似乎我将被迫通过该功能的所有组件。
Extend React生命周期挂钩(例如,在每个ComponentDidMount上添加一个打印语句(以前也问过类似的问题,但解决方案只打印父组件的生命周期,而不打印子组件?
感谢您的帮助,如果您提供一段代码片段,我将不胜感激。
React中我能想到的唯一解决方案是创建一个新的基类来扩展React Component基类。将生命周期方法添加到基类中,然后您创建的每个组件都会扩展这个新类(如果您希望它使用生命周期方法(。
class NewBaseClass extends React.Component {
componentDidMount() {
console.log('do something on mount')
}
}
class CustomComponent extends NewBaseClass {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
我还没有测试过这个确切的用例,让我知道它是否有帮助:(
您可以实现类似于以下内容的HOC:
function withLifeCycleLogs(WrappedComponent) {
const Enhanced = class extends React.Component {
componentDidMount() {
console.log(`Component ${WrappedComponent.name} did mount`);
}
componentDidUpdate(prevProps) {
console.log(`Component ${WrappedComponent.name} did update`, {
// Uncomment below lines to inspect props change
// prevProps,
// nextProps: this.props
});
}
componentWillUnmount() {
console.log(`Component ${WrappedComponent.name} will unmount`);
}
render() {
return <WrappedComponent {...this.props} />;
}
};
// Wrap the display name for easy debugging
// https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging
Enhanced.displayName = `WithLifeCylceLogs${getDisplayName(WrappedComponent)}`;
// Static Methods Must Be Copied Over
// https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over
//
// hoistNonReactStatic(Enhanced, WrappedComponent);
return Enhanced;
}
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || "Component";
}
class Counter extends React.Component {
render() {
return (
<div>
<button onClick={this.props.increment}>Increment</button>
<p>{this.props.counter}</p>
<button onClick={this.props.unmount}>Unmount Counter</button>
</div>
);
}
}
const CounterContainer = withLifeCycleLogs(Counter);
class App extends React.Component {
constructor() {
super();
this.state = {
counter: 0,
counterVisible: true
};
}
increment = () => {
this.setState((state) => ({ ...state, counter: state.counter + 1 }));
};
unmountCounter = () => {
this.setState((state) => ({ ...state, counterVisible: false }));
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{this.state.counterVisible && (
<CounterContainer
counter={this.state.counter}
increment={this.increment}
unmount={this.unmountCounter}
/>
)}
</div>
);
}
}
const AppContainer = withLifeCycleLogs(App);
const rootElement = document.getElementById("root");
ReactDOM.render(
<AppContainer />,
rootElement
);
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<div id="root">
</div>
是的,您需要将每个组件传递给withLifeCycleLogs
函数。但这真的很简单,不需要太多空间,看看这个:
class AwesomeComponent extends React.Component {
//
}
export default withLifeCylceLogs(AwesomeComponent);
这就像在Spring中使用注释(如果我错了,请纠正我(
代码沙盒