1、react hooks是用来做什么的?
加入hooks,让react函数组件更加的灵活
hooks之前,React存在很多问题:
- 1、组件间服用状态逻辑难
- 2、复杂组件变的难以理解,高阶组件和函数组件的嵌套过深
- 3、class组件的this问题
- 4、难以记忆的生命周期
hooks有:
- useState()
- useEffects()
- useReducer()
- useRef()
- useCallback()
- useContext()
- useMemo()
2、useReducer()
是一种让函数组件保存状态的方式
reducer 接收两个参数,state,action
3、useContext()
在跨组件层级获取数据时简化获取数据的代码
import React, { useState, createContext, useContext } from "react";
const CountContext = createContext(0);//创建Context
const Example = () => {
const [count, setCount] = useState<number>(0);
return (
<div>
<p>父组件点击数量:{count}</p>
<button onClick={() => setCount(count + 1)}>{"点击+1"}</button>
// 使用CountContext.Provider包裹需要接收参数的子组件,并通过value传值
<CountContext.Provider value={count}>
<Counter />
</CountContext.Provider>
</div>
);
};
const Counter = () => {
const count = useContext(CountContext);
return <p>子组件获得的点击数量:{count}</p>;
};
export default Example;
4、useEffect()
类似生命周期函数,可以把useEffect看做
- 模拟componentDidMount - useEffect 依赖 [ ]
- 模拟compenentDidUpdate - useEffect 无依赖 ,或者 依赖 [a,b,c]
- 模拟componentWillUnMount - useEffect 中返回一个函数
5、react事件机制
React并不是将click事件绑定到了div的真实DOM上,而是在document处监听了所有的事件,当事件发生并且冒泡到document处的时候,React将事件内容封装并交由真正的处理函数运行。这样的方式不仅仅减少了内存的消耗,还能在组件挂在销毁时统一订阅和移除事件。
除此之外,冒泡到document上的事件也不是原生的浏览器事件,而是由react自己实现的合成事件(SyntheticEvent)。
e.stopPropagation()
,只能阻止react的合成事件的冒泡触发
e.nativeEvent.stopImmediatePropagation()
阻止document上同类事件的调用
6、react事件和普通的HTML事件有什么不同
区别:
- 对于事件名称命名方式,原生事件为全小写,react 事件采用小驼峰;
- 对于事件函数处理语法,原生事件为字符串,react 事件为函数;
- react 事件不能采用 return false 的方式来阻止浏览器的默认行为,而必须要地明确地调用preventDefault()来阻止默认行为。
合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:
- 兼容所有浏览器,更好的跨平台;
- 将事件统一存放在一个数组,避免频繁的新增与删除(垃圾回收)。
- 方便 react 统一管理和事务机制。
事件的执行顺序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为需要冒泡到document 上合成事件才会执行。
7、react组件中怎么做事件代理,原理是什么
8、对fragement的理解,使用场景是什么
在React中,组件返回的元素只能有一个根元素。为了不添加多余的DOM节点,我们可以使用Fragment标签来包裹所有的元素,Fragment标签不会渲染出任何元素。
官方解释:
React 中的一个常见模式是一个组件返回多个元素。Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
9、如何获取组件对应的DOM元素
可以用ref来获取某个子节点的实例
10、react可以在render阶段访问refs吗?
不可以
11、对react插槽portals的理解,使用场景
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案
Portals是16提供的官方解决方案,使得组件可以脱离父组件层级挂载在DOM树的任何位置。通俗来讲,就是我们 render 一个组件,但这个组件的 DOM 结构并不在本组件内。
12、如何避免不必要的render
- shouldComponentUpdate 和 PureComponent
- 使用 React.memo
- useCallback、useMemo
13、对react context的理解
在React中,数据传递一般使用props传递数据,维持单向数据流,这样可以让组件之间的关系变得简单且可预测,但是单项数据流在某些场景中并不适用。单纯一对的父子组件传递并无问题,但要是组件之间层层依赖深入,props就需要层层传递显然,这样做太繁琐了。
简单说就是,当你不想在组件树中通过逐层传递props或者state的方式来传递数据时,可以使用Context来实现跨层级的组件数据传递。
hook后就是useContext
14、react受控组件和非受控组件
在使用表单来收集用户输入时,例如<input><select><textearea>等元素都要绑定一个change事件,当表单的状态发生变化,就会触发onChange事件,更新组件的state。这种组件在React中被称为受控组件。
受控组件更新state的流程:
- 可以通过初始state中设置表单的默认值
- 每当表单的值发生变化时,调用onChange事件处理器
- 事件处理器通过事件对象e拿到改变后的状态,并更新组件的state
- 一旦通过setState方法更新state,就会触发视图的重新渲染,完成表单组件的更新
受控组件缺陷:
表单元素的值都是由React组件进行管理,当有多个输入框,或者多个这种组件时,如果想同时获取到全部的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种情况,出现了非受控组件。
非受控组件:
15、类组件和函数组件有什么异同
类组件是基于面向对象编程的,它主打的是继承、生命周期等核心概念;而函数组件内核是函数式编程,主打的是 immutable、没有副作用、引用透明等特点。
16、setState是同步还是异步
setState 并不是单纯同步/异步的,它的表现会因调用场景的不同而不同。在源码中,通过 isBatchingUpdates 来判断setState 是先存进 state 队列还是直接更新,如果值为 true 则执行异步操作,为 false 则直接更新。
- 异步:在 React 可以控制的地方,就为 true,比如在 React 生命周期事件和合成事件中,都会走合并操作,延迟更新的策略。
- 同步:在 React 无法控制的地方,比如原生事件,具体就是在 addEventListener 、setTimeout、setInterval 等事件中,就只能同步更新。
一般认为,做异步设计是为了性能优化、减少渲染次数
setState的第二个参数作用?
第二个参数是一个可选的回调函数。这个回调函数将在组件重新渲染后执行
17、组件通信方式有哪些
18、为什么useState要使用数组而不是对象
useState 返回的是 array 而不是 object 的原因就是为了降低使用的复杂度,返回数组的话可以直接根据顺序解构,而返回对象的话要想使用多次就需要定义别名了。
19、react hooks解决了那些问题
(1)在组件之间复用状态逻辑很难
(2)复杂组件变得难以理解
(3)难以理解的 class
20、react hooks的使用限制有哪些
- 不要在循环、条件或嵌套函数中调用 Hook;
- 在 React 的函数组件中调用 Hook。
那为什么不要在循环、条件或嵌套函数中调用 Hook 呢?因为 Hooks 的设计是基于数组实现。在调用时按顺序加入数组中,如果使用循环、条件或嵌套函数很有可能导致数组取值错位,执行错误的 Hook。当然,实质上 React 的源码里不是数组,是链表。
21、react hooks在平时开发中需要注意的问题和原因
22、react hooks和生命周期的关系
23、react性能优化有哪些
react性能优化有哪些_景尘的博客-优快云博客_性能优化 render重新bind
24、react fiber解决了什么问题,diff算法
【react】fiber解决了什么问题,及diff算法_景尘的博客-优快云博客
25、react版本更新解决了什么问题
react版本更新解决了那些问题_react18解决了哪些问题_景尘的博客-优快云博客
26、怎么获取上一次值?
useRef可以获取上一次的值,只要state没有更新,就不会触发页面渲染,那么useRef拿到的就会是上一次的值,因为xx.current变化不会触发组件的重新渲染
//创建一个存储DOM对象的容器
const demoRef = useRef()
//获取
demoRef.current
<demo ref={demoRef}/>
27、Suspense
React 16.6 新增了<Suspense>
组件,让你可以“等待”目标代码加载,并且可以直接指定一个加载的界面(像是个 spinner),让它在用户等待的时候显示
const ProfilePage = React.lazy(() => import('./ProfilePage')); // 懒加载
// 在 ProfilePage 组件处于加载阶段时显示一个 spinner
<Suspense fallback={<Spinner />}>
<ProfilePage />
</Suspense>
Suspense会为组件包装一层异常Promise,异常结束后重新渲染ProfilePage,在此期间显示fallback组件
Suspense要解决的两个问题:
- 代码分片;
- 异步获取数据
28、通过 React.lazy
实现组件的懒加载
const Foo = React.lazy(() => import('../components/Foo'));