react 18属性和方法
const ReactKeys = ["Children","Component","PureComponent","Fragment", // 空标签"Profiler", // 性能审查"StrictMode", // 严格模式"Suspense","lazy","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","cloneElement","createContext","useContext","createElement","createFactory","createRef","forwardRef","useImperativeHandle", // 指定访问的API"isValidElement", // 是不是一个 react元素"memo","startTransition","unstable_act","useCallback", // 缓存回调函数"useDebugValue","useDeferredValue","useEffect","useInsertionEffect","useLayoutEffect","useId", // 创建当前组件的唯一身份"useMemo", // 缓存,类似 vue 的 computed 计算属性"useReducer","useRef","useState","useSyncExternalStore", // 从外部获取数据源"useTransition","version" // 版本号]
isValidElement
- 必须是 Object对象
- 不能为空
- 对象中要有 $$typeof 属性,且值必须是 REACT_ELEMENT_TYPE
REACT_ELEMENT_TYPE:一个 Symbol或 16进制的数值。
export const REACT_ELEMENT_TYPE = hasSymbol? Symbol.for('react.element') : 0xeac7;
新的API
useId
useSyncExternalStore
useInsertionEffect
useDeferredValue
应用场景:
- Select,或 Input的模糊搜索
- 复杂计算或网络请求 ```tsx const [inputValue, setInputValue, cancelUpdate] = useDeferredValue(‘’, { timeoutMs: 1000, // 延迟 1000ms,单位毫秒 maximumTimeMs: 5000, // 最长延迟 5000ms 更新,ms equalityFn: (a,b) => a === b, // 状态对比 });
useEffect(() => { return () => { cancelUpdate(); } }, [])
缺点1. 固定的任务设置延迟,和 debounce不一样,会导致数据不一致2. 搜索结果不会立即更新,导致关键字和搜索结果不一致,导致数据不一致1. 使用 useTransition解决3. 如果在状态更新期间,组件已卸载或销毁,可能导致内存泄露1. 使用 cancelUpdate 解决<a name="chkZQ"></a>### useIdID代表,当前组件在组件树中的层级结构,服务端和客户端的ID是一致的<a name="g6862"></a>### useSyncExternalStore强制同步更新数据<a name="JJAzu"></a>### useInsertionEffectuseInsertionEffect,需要对 DOM操作时用,例如- 自动滚动- 按需加载```tsxfunction App() {// 滚动到顶部useInsertionEffect(() => {window.scrollTo(0, 0)})}
新并发API
startTransition
useDeferredValue
startTransition
不紧急的更新,空闲时更新
import { useEffect, useState, startTransition, useDeferredValue } from 'react'function App() {const [state, setState] = useState([])useEffect(() => {// 包裹方法startTransition(() => {setState(new Array(10000).fill(100))})}, []);// 包裹值const deferredList = useDeferredValue(state);return (<>{state.map(it => <div key={it}/>{it}</div>)}{deferredList.map(it => <div key={it}/>{it}</div>)}</>)}
新模式
Concurrent Mode
Strict Mode
Concurrent Mode 并发模式
异步可中断更新
react18 新特性
- render
- setState批处理
- flushSync
- 卸载组件时的更新状态警告⚠️
- react组件的返回值
- Strict Mode 严格模式,重复2次渲染
- Suspense不需要 fallback来捕获异常❌
render
import ReactDOM from 'react-dom'const root = document.getElementById('root');// react 18ReactDOM.createRoot(root).render(<App />);root.unmount(); // 从 DOM中卸载组件// react 17ReactDOM.render(<App />, root)ReactDOM.unmountComponentAtNode(root)
setState批处理
setState不保证 state会立即更新,操作会被延迟批量调用。
批量就是延迟的原因。
setState并不是立即更新的命令,假设setState()是同步的,如果在一次点击函数中更新了两次state,组件就会被渲染两次;
若把setState()收集起来统一处理,组件就只需要被渲染一次。这就是setState()异步的思路;
在一个周期内,每遇到一个setState()React会将它放到队列中,最后会对多个setState()进行批处理。
ReactDOM.unstable_batchedUpdates
flushSync 同步更新
flushSync可以用于强制刷新
import { flushSync } from 'react-dom'function App() {const [val, setVal] = useState(0);const [value, setValue] = useState(0);function onClick() {flushSync(() => setVal(val => val + 1))flushSync(() => setValue(val => val + 1))}return (<Button onClick={onClick}></Button>)}
Strict Mode 严格模式
严格模式,二次渲染问题
react 17,使用严格模式,组件会渲染 2次。
react18, 取消了这个限制,安装了 React DevTools后,第二次渲染的日志信息,显示为灰色。
react@version 18.2.0
