面试题答案
一键面试高阶组件(HOC)
- 复用逻辑:HOC 是一个函数,它接受一个组件并返回一个新的组件。通过这种方式,可以将通用的逻辑(如数据获取、权限验证等)抽离出来,应用到多个不同的组件上。例如,创建一个用于数据获取的 HOC:
import React from'react';
const withData = (fetchFunction) => (WrappedComponent) => {
return class extends React.Component {
state = {
data: null,
loading: false,
error: null
};
componentDidMount() {
this.setState({ loading: true });
fetchFunction()
.then(data => this.setState({ data, loading: false }))
.catch(error => this.setState({ error, loading: false }));
}
render() {
const { data, loading, error } = this.state;
return <WrappedComponent data={data} loading={loading} error={error} {...this.props} />;
}
};
};
export default withData;
然后在需要数据获取的组件中使用:
import React from'react';
import withData from './withData';
const fetchUserData = () => Promise.resolve({ name: 'John' });
const UserComponent = ({ data, loading, error }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>{data.name}</div>;
};
export default withData(fetchUserData)(UserComponent);
- 状态管理:HOC 可以通过传递 props 来管理子组件的状态。例如,在权限验证的 HOC 中,可以根据验证结果传递不同的 props 给子组件,控制子组件的渲染和行为。
Render Props
- 复用逻辑:Render Props 是一种通过一个函数 prop 来共享代码的技术。与 HOC 不同,它将逻辑暴露给调用者,调用者可以更灵活地使用这些逻辑。例如,创建一个用于鼠标位置追踪的组件:
import React from'react';
class MouseTracker extends React.Component {
state = {
x: 0,
y: 0
};
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove);
}
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove);
}
handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
};
render() {
const { x, y } = this.state;
return this.props.render({ x, y });
}
}
export default MouseTracker;
在其他组件中使用:
import React from'react';
import MouseTracker from './MouseTracker';
const App = () => (
<MouseTracker render={({ x, y }) => (
<div>
<p>Mouse position: x: {x}, y: {y}</p>
</div>
)} />
);
export default App;
- 状态管理:Render Props 同样可以通过传递状态数据给渲染函数来管理状态的使用。
权衡因素
- 代码结构和可读性:
- HOC:HOC 的使用使得代码结构更像是“包裹”,如果有多个 HOC 嵌套,可能会使组件的层级结构变得复杂,影响可读性。例如
withRouter(withData(UserComponent))
。 - Render Props:Render Props 基于函数调用,代码结构更加扁平,调用者对逻辑的使用更加清晰,但如果渲染函数很长,也会影响可读性。
- HOC:HOC 的使用使得代码结构更像是“包裹”,如果有多个 HOC 嵌套,可能会使组件的层级结构变得复杂,影响可读性。例如
- 性能:
- HOC:每次 HOC 包裹一个组件都会创建一个新的组件实例,可能会导致不必要的重新渲染。但可以通过
React.memo
等方式进行优化。 - Render Props:同样可能会因为函数的重新传递导致不必要的渲染,但通过使用
React.memo
或者useCallback
等钩子可以优化。
- HOC:每次 HOC 包裹一个组件都会创建一个新的组件实例,可能会导致不必要的重新渲染。但可以通过
- 灵活性:
- HOC:HOC 的逻辑是封装好的,调用者只能通过 props 来配置,灵活性相对较低。
- Render Props:Render Props 将逻辑暴露给调用者,调用者可以根据自己的需求灵活组合和使用,灵活性更高。
- 兼容性:
- HOC:HOC 是 React 早期就支持的模式,兼容性好,对于类组件和函数组件都适用。
- Render Props:虽然也适用于类组件和函数组件,但在函数组件中使用 React Hooks 后,部分场景下 Render Props 的使用场景有所减少。