React 面试
1. 什么是HOC高阶组件
比如 react-redux 中的 connect 组件,接受一个组件,返回一个新的组件,给新的组件添加新的组件
缺点 : 容易形成嵌套地狱
现在主要用hook 使用状态
2. 函数/类 组件中如何使用state
组件内部state,适合在本组件使用。有点灵活,缺点难以实现组件共享
函数组件 用useState useReducer
类组件 this.state 修改this.setState
组件外的state ,用状态管理库。redux dva umi
3. redux 原理
修改状态,使用subscribe订阅刷新页面,后有了hook,usedDispatch之类的hook
将订阅页面更新放到了页面里面
redux 中的subscribe返回值是取消订阅 (想想源码的return
4. 常见组件性能优化手段
4-1. 复用组件
复用的前提必须满足三个条件:同一层级下,同一类型,同一个key值,所以我们尽量保证这三者的稳定性
常见错误比如key=Match.random() 做key值 这样就会每次卸载旧的组件 生成新的组件
不规范写法 用key = index 但是组件如果发生拖拽啥的就寄了
4-2. 尽量减少组件的重新render
-
在类组件中 通过shouldcomponentupdate生命周期判断
this.props.item !==nextPpropsitem 就return false 不更新 -
类组件中 使用purcomponent 内置了通过shouldcomponentupdate,通过判断props是否有变化
-
函数组件中 使用memo 其实HOC高阶组件,memo会检查属性是否发生变化,来选择是否重新渲染,源码会进行浅比较会直接进入bailout,也可以自定义函数,放进去一个callback函数
const a = memo(function Home() { return(<> home page </>) },(pre,current)=>{ return pre.item !== current.item })
-
useMemo 把返回值返回到filber节点上
export default const a =({item}) =>{ //这里child组件并不依赖item的变化重新更新
return useMemo (() => {
<div>
{item}
<Child/>
</div>
})
}
-
useCallback 可以缓存函数
使用useCallback(fn,deep) == useMemp (() => fn,deep) -
context value 只要发生变化 消费这个组件的后代consumer都要更新 所以要尽量的精简实用 比如项目里页面初次加载就把所有的dymanic数据和static数据全请求出来
比如拆分不想管的context 比如俩个不想关联的context 拆开 这样就不用修改某个的时候 全部渲染了
5. hook解决了什么问题
- 组件之间状态难以复用,比如最早的redux ,如果想用store里面的值,只能每个组件页面进来订阅,页面销毁取消订阅。最好的方式就是些一个HOC高阶组件,让所有组件进来就订阅, 但是也会形成
嵌套地狱,后面几个括号,不方便阅读
有了hook之后就是一个自定义hook,函数组件之间的状态服用,直接useSelector - 复杂组件难以理解
一个生命周期里写了好几个组件的逻辑,臃肿,hook 可以写几个副作用,方便阅读,甚至可以写自定义hook - 类组件的this
6. 什么是自定义hook
就是自己封装的hook 最经典的就是alibaba/ahooks 里面的一些定时器,forceupdate
7,为什么hook出现之后 就可以定义state了 或者说为什么之前函数组件不能有自己的状态
之前函数组件不能保存状态是因为当状态改变的时候 页面就要重新渲染 这样定义在函数里面的变量就会重新生成复制,肯定不行,如果定义在函数外面全局污染 直接傻杯
所以hook出现后 封装了useState 和 useReducer方法 把state状态保存到了filber上
柯利化
记住这个柯利化
javascript">function addware(...arg) {
return (params) => (arg1) => {
console.log('ageOutSide',arg)
console.log('inside1', arg1)
console.log('inside2', params)
}
}
const useEnhancer = (enhancer) => {
return enhancer('params1')('params2')
}
addware('addwareparams')
useEnhancer(addware('addwareparams'))