程序员的金三银四求职宝典
1.用类组件和函数组件分别编写react的不同 生命周期
在 React 中,类组件和函数组件的生命周期函数有所不同。以下是分别使用类组件和函数组件编写的挂载、更新和卸载阶段的生命周期函数示例:
类组件:
import React, {
Component } from 'react';
class LifecycleComponent extends Component {
constructor(props) {
super(props);
console.log('Constructor called');
}
componentDidMount() {
console.log('Component did mount');
}
componentDidUpdate(prevProps, prevState) {
console.log('Component did update');
}
componentWillUnmount() {
console.log('Component will unmount');
}
render() {
console.log('Render called');
return (
<div>
Lifecycle Component
</div>
);
}
}
export default LifecycleComponent;
函数组件:
import React, {
useEffect } from 'react';
const FunctionComponent = () => {
useEffect(() => {
console.log('Component did mount');
return () => {
console.log('Component will unmount');
};
}, []);
useEffect(() => {
console.log('Component did update');
});
console.log('Render called');
return (
<div>
Function Component
</div>
);
};
export default FunctionComponent;
在上面的示例中:
- 类组件中的生命周期函数包括
constructor
、componentDidMount
、componentDidUpdate
和componentWillUnmount
。 - 函数组件中使用
useEffect
钩子模拟了生命周期函数,第一个useEffect
用于模拟componentDidMount
和componentWillUnmount
,第二个useEffect
用于模拟componentDidUpdate
。
无论是类组件还是函数组件,都能够实现 React 组件的生命周期功能。根据实际需求选择适合的编码方式。
2. useMemo,ReactMemo,useCallBack,三者的区别
在 React 中,useMemo
、React.memo
和 useCallback
是用于性能优化的钩子函数,它们的作用和用法略有不同。以下是它们的区别:
-
useMemo:
useMemo
用于在渲染过程中执行一些计算,并将计算结果进行缓存,只有当依赖项发生变化时才会重新计算。- 语法:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo
的第一个参数是一个函数,用于计算需要缓存的值,第二个参数是一个依赖数组,只有当依赖项发生变化时,才会重新计算值。
-
React.memo:
React.memo
是一个高阶组件,用于包裹函数组件,用于对组件进行浅比较的 PureComponent 的功能。- 当函数组件的 props 没有发生变化时,
React.memo
将会使用之前的渲染结果,从而避免不必要的重新渲染。 - 语法:
const MemoizedComponent = React.memo(MyComponent);
React.memo
只接受一个参数,即需要进行性能优化的函数组件。
-
useCallback:
useCallback
用于缓存一个回调函数,并且只有在依赖项发生变化时才会重新创建这个回调函数。- 语法:
const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
useCallback
的第一个参数是一个回调函数,第二个参数是一个依赖数组,只有当依赖项发生变化时,才会重新创建回调函数。
综上所述,useMemo和useCallback
接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值,区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数。
useCallback(fn,deps)
相当于 useMemo(()=> fn,deps)
。类似 shouldComponentUpdate
, 判定该组件的 props 和 state 是否有变化,从而避免每次父组件render时都去重新渲染子组件
useCallback返回一个函数,当把它返回的这个函数作为子组件使用时,可以避免每次父组件更新时都重新渲染这个子组件,子组件一般配合 memo 使用
React.memo()
和 useMemo()
的主要区别
从上面的例子中,我们可以看到 React.memo() 和 useMemo() 之间的主要区别:
React.memo() 是一个高阶组件,我们可以使用它来包装我们不想重新渲染的组件,除非其中的 props 发生变化
useMemo() 是一个 React Hook,我们可以使用它在组件中包装函数。 我们可以使用它来确保该函数中的值仅在其依赖项之一发生变化时才重新计算
虽然 memoization 似乎是一个可以随处使用的巧妙小技巧,但只有在绝对需要这些性能提升时才应该使用它。 Memoization 会占用运行它的机器上的内存空间,因此可能会导致意想不到的效果。
3.useEffect
和 useMemo
区别
useEffect是在DOM改变之后触发,useMemo在DOM渲染之前就触发
useMemo是在DOM更新前触发的,就像官方所说的,类比生命周期就是[shouldComponentUpdate]
useEffect可以帮助我们在DOM更新完成后执行某些副作用操作,如数据获取,设置订阅以及手动更改 React 组件中的 DOM 等
4.不要在这个useMemo函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo
5.在useMemo中使用setState你会发现会产生死循环,并且会有警告,因为useMemo是在渲染中进行的,你在其中操作DOM后,又会导致触发memo
4.问题:既然memo对性能优化有好处,为什么不把每个组件都包一下?
因为memo有缓存,大量使用,造成大量的性能开销。其次,props的比较只是浅比较,会有一些坑(解决浅比较的方式有:重新定义一个对象或者数组比如{…object,1},不用pop或者push)
useCallback 和 useMemo 仅仅在后续渲染(也就是重渲染)中起作用,在初始渲染中它们反而是有害的
useCallback 和 useMemo 作用于 props 并不能避免组件重渲染。只有当每一个 prop 都被缓存,且组件本身也被缓存的情况下,重渲染才能被避免。
只要有一丁点疏忽,那么你做的一切努力就打水漂了。所以说,简单点,把它们都删了吧。把包裹了“纯 js 操作“的 useMemo 也都删了吧。
与组件本身的渲染相比,它缓存数据带来的耗时减少是微不足道的,并且会在初始渲染时消耗额外的内存,造成可以被观察到的延迟。
5. useEffect
,useLayoutEffect
,useInsertionEffect
分别用来干什么?
1.useEffect: 用于副作用捕获,在 dom 元素渲染之后调用,常用于页面数据处理工作。
2.useLayoutEffect: useEffect 的一个版本,在 DOM 更新之后同步执行,但在浏览器绘制之前执行,常用于页面元素布局工作,可能会阻塞页面渲染。
3.useInsertionEffect: useEffect 的一个版本,在 DOM 更新前执行。常用于 CSS-in-JS 插入动态样式。
6. useEffect 执行机制,写出下面代码运行的结果
import React, {
useState } from "react";
import ReactDOM from "react-dom";
function App() {
const [n, setN] = useState(0);
const onClick = () => {
setN(n + 1);
};
React.useEffect(() => {
console.log("App");
return () => {
console.log("App挂了");
};
});
return (
<div className="App">