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>
### useId
ID代表,当前组件在组件树中的层级结构,服务端和客户端的ID是一致的
<a name="g6862"></a>
### useSyncExternalStore
强制同步更新数据
<a name="JJAzu"></a>
### useInsertionEffect
useInsertionEffect,需要对 DOM操作时用,例如
- 自动滚动
- 按需加载
```tsx
function 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 18
ReactDOM.createRoot(root).render(<App />);
root.unmount(); // 从 DOM中卸载组件
// react 17
ReactDOM.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