React面试题
什么是 jsx
jsx ( javascript xml ) , 是javascript 语法的扩展,
jsx 是React.createElement 的语法糖。
jsx优点:
体现了React申明式的优点,
什么是 React 副作用
就是除了状态相关的逻辑,比如网络请求,监听事件,查找 dom。
在react中,有些副作用需要清除,有些副作用无需清除。
比如手动变更dom, 记录日志这些都无需清除。
而订阅外部数据源、添加定时器等容易造成内存泄露,就很有必要清除。
例如: 组件已经卸载了,但定时器还没有关闭,那么就会报错!!
useEffect(() => {
const source = axios.CancelToken.source();
const fetchData = async () => {
try {
const response = await Axios.get("/companies", {
cancelToken: source.token
});
} catch (error) {
if (Axios.isCancel(error)) {
} else {
throw error;
}
}
};
fetchData()
return () => {
source.cancel();
};
}, [companies]);
参看资料:
https://www.jianshu.com/p/e1ff909aca88
https://www.jianshu.com/p/fdab5a6fa1aa
纯函数
概念:
1. 一个函数,它的计算不依赖外部的变量,它就是纯函数。
2. 一个函数在执行过程中发生了外部可变的变化,就不是纯函数,反之则是。
一般来讲就是发生了和运算返回值无关的事,就不是纯函数例如:
修改外部作用域 / 全局变量;
修改传入的参数,发送请求、console.log 、操作dom都属于副作用。
useEffect 和useLayoutEffect 的区别
useLayoutEffect:是在所有DOM变更之后浏览器渲染之前调用,既同步调用
useEffect:是在组件渲染到屏幕之后执行,既异步调用
useLayoutEffect 相比 useEffect,通过同步执行状态更新可解决一些特性场景下的页面闪烁问题。
useEffect 可以满足百分之99的场景,而且 useLayoutEffect 会阻塞渲染,请谨慎使用
什么是useRef
返回的 ref 对象在组件的整个生命周期内保持不变
当更新 current 值时并不会 re-render ,这是与 useState 不同的地方
采用useRef,作为组件实例的变量,保证获取到的数据肯定是最新的。
三、useRef与createRef的区别
在一个组件的正常的生命周期中可以大致分为3个阶段:
从创建组件到挂载到DOM阶段。初始化props以及state, 根据state与props来构建DOM
组件依赖的props以及state状态发生变更,触发更新
销毁阶段
第一个阶段,useRef与createRef没有差别
第二个阶段,createRef每次都会返回个新的引用; 而useRef不会随着组件的更新而重新创建
第三个阶段,两者都会销毁
useRef可以用来定义变量,这些变量更改之后不会引起页面重新渲染。
useRef也可以用来区分初始渲染还是更新(通过current有没值,具体见示例库里的didOrUpdate.tsx)
在DOM节点上定义ref属性,通过.current就可以获取到该DOM元素
通过forwardRef就可以给函数子组件传入ref属性。
使用useImperativeHandle用于定义暴露给父组件的ref方法
useEffect使用异步函数
useEffect 不能直接使用async await 语法糖.
useEffect(async ()=>{
const res = await getData()
},[]);
useEffect 的回调参数返回的是一个清除副作用的 clean-up 函数。
因此无法返回 Promise,更无法使用 async/await
1.
useEffect(() => {
(async function getDatas() {
await getData();
})();
}, []);
return <div></div>;
};
2.
useEffect(() => {
const getDatas = async () => {
const data = await getData();
setData(data);
};
getDatas();
}, []);
自定义hook & 高阶组件
自定义hook :
将一些常用的,跨越多个组件的hook逻辑代码抽离出去就是一个自定义hook。
自定义 hook 内部仍使用hook, 因此其内部同样也要遵循hook规则。
每个组件间的 state 是完全独立的。
Hook 是一种复用 状态逻辑 的方式,它不复用 state 本身。
事实上 Hook 的每次调用 都有一个完全独立的state ——
因此你可以在单个组件中多次调用同一个自定义 Hook。
规则:
1. 函数名以use开头
2. 其他组件调用自定义hook, 也应该放到最顶层。
高阶组件同样可以封装重复的逻辑代码,达到代码复用,减少冗余代码的作用。
但是:
1. 高阶组件 没有 自定义hook来的优雅,
2. 高阶组件也会导致组件嵌套层次过深。