React18新特性
1.useTransition:在状态修改时不会立即更定DOM,减少视觉上的延迟,使用体验更加丝滑,性能方面也会更好。例如对于输入框,如果将其写为可控组件,那么在输入值过程中,输入框这个DOM也在同步更新,而使用useTransition之后,可以将其改为无需完全同步,使得输入起来更加的平滑。将修改状态的代入写入startTransition的回调函数内即可。
import React, { useState, useTransition } from "react";
export default function SearchCities() {
const [text, setText] = useState("Am");
const [searchQuery, setSearchQuery] = useState(text);
const [isPending, startTransition] = useTransition();
return (
<main>
<input
type="text"
value={text}
onChange={(e) => {
setText(e.target.value)
startTransition(() => {
setSearchQuery(e.target.value)
})
}}
/>
<CityList searchQuery={searchQuery} />
</main>
);
};
2.新增client和server:前者是客户端渲染,后者是服务端渲染
import React from 'react';
import ReactDOM from 'react-dom/client';
import ReactDOM from 'react-dom/server';
import App from './App';
const root = document.getElementById('root');
ReactDOM.createRoot(root).render(<App />);
3.对于ts提示,所有组件需要手动写Children的类型,系统将不再自带
interface MyButtonProps {
color: string;
children?: React.ReactNode;
}
const MyButton: React.FC<MyButtonProps> = ({ color, children }) => {
return <div>{children}</div>;
};
export default MyButton;
4.flushSync:清除批量更新。React特性在同步代码中,所有的状态改变都是一次性批量处理的,这样DOM只用更新一遍。但对于特殊的情况是需要退出批量更新的,这时候可以把状态变化相关的代码放到flushSync的回调函数中。回调函数中为批量更新,函数之外就不是了。
function handleClick() {
flushSync(() => {
// 批量更新
setCount(3);
setFlag(true);
});
以上批量更新完成之后,再进行以下状态的更新
setLoading(false);
}
5.useDeferredValue:用于延迟更新组件状态,可以自定义配置延迟时间,以降低这部分状态带来的页面重新渲染的优先级。所以当遇到部分渲染优先级处于最低的状态,使用useDeferredValue即可。
useDeferredValue 与 useTransition的异同:
- 同:useDeferredValue 本质上和内部实现与 useTransition 一样都是标记成了非紧急更新任务。
- 异:useTransition 是把更新任务变成了延迟更新任务,而 useDeferredValue 是产生一个新的值,这个值作为延时状态.
useDeferredValue 与 debounce的区别:debounce 即 setTimeout 总是会有一个固定的延迟,而 useDeferredValue 的值只会在渲染耗费的时间下滞后,在性能好的机器上,延迟会变少,反之则变长。
import React, { useState, useDeferredValue } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const deferredCount = useDeferredValue(count, { timeoutMs: 500 });
function handleClick() {
setCount(count + 1);
}
return (
<>
<div>{deferredCount}</div>
<button onClick={handleClick}>+1</button>
</>
);
}
export default App;
6.useId:用于解决 SSR 时客户端与服务端难以生成统一的 ID 的问题。因为服务器渲染时提供的html是无序的,useId 的原理就是每个id代表该组件在组件树中的层级结构。
import React, { useId } from 'react';
const App = () => {
const id = useId();
return (
<div>useId</div>
);
}
export default App;
7.useInsertionEffect:一般只用于css-in-js库相关。这个hooks是在dom生成并完全挂载之前执行,一般运用在提前挂载style脚本。
const useCSS = rule => {
useInsertionEffect(() => {
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
};
const App: React.FC = () => {
const className = useCSS(rule);
return <div className={className} />;
};
export default App;