大家好呀,我是小肚肚肚肚肚哦!这是我的React官网解读系列!
React 官网 beta 版本已经变为了正式版,但仍旧没有中文版。对于国内不少开发者来说增加了不少麻烦。我这里以前端开发的角度归纳总结一下,把其中大家重点使用的部分介绍给大家。
官网地址:React
startTransition
我们在讲 useTransition 的一节我们讲过,通过 hook 可以获取到这个 API,推荐结合 hook 一起使用。
当然也可以直接引入:
js
import { startTransition } from 'react';
function TabContainer() {
const [tab, setTab] = useState('about');
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab);
});
}
// ...
}
他的作用是防止 UI 阻塞,做到前端异步非阻塞渲染。具体使用方式见 useTransition。
注意事项
Caveats
startTransition
不会追踪渲染 pending 的状态. 想要获取渲染实时状态,请使用useTransition
.- 使用它包裹 state 的
set
函数来实现跟该 state 相关的渲染过渡。 如果想要响应2 props 变化来实现渲染过渡,请使用useDeferredValue
. startTransition
内部函数必须是同步的.- 标记为 transition 的 state 更新会被其他 state 的更新打断渲染,在其他渲染调度结束后再次想重新执行该渲染.
- 不能用于控制文本输入组件.
- 如果同时有多个在运行的过渡,React 会把他们合并一起处理。这个方案似乎是个性能缺陷,随后的版本可能会修复它。
createContext
顾名思义,就是创建一个 context 对象,一般结合 hook 一起使用,可以参考我 useContext 的文章。
官网的部分描述与 useContext 有重复,这里及直接讲使用案例。
使用案例
- 配置全局变量
js
// 放在全局,创建时的默认值一般可以不用传递,在 provider 时会配置初始值的
const ThemeContext = createContext();
const AuthContext = createContext();
我们定义主题信息和认证信息,用它包裹根组件:
jsx
const [theme, setTheme] = useState('dark');
const [currentUser, setCurrentUser] = useState({ id: 1 });
<ThemeContext.Provider value={theme}>
<AuthContext.Provider value={currentUser}>
<Page />
</AuthContext.Provider>
</ThemeContext.Provider>
在包裹的内部组件中,无论多深的层级,都可以这样使用来获取 value 值:
js
const theme = useContext(ThemeContext); // dark
确保 ThemeContext 是一开始定义的那个单例
他踢动了一个单向数据流,可以从顶向下传递动态响应式数据。如果在入口处维护一些 state,暴露出事件来给各个业务模块调用,就可以实现一个类似 redux 的功能。
- 局部引用
js
// Button.js
import { ThemeContext } from './Contexts.js';
比如上面的例子,我们全局配置了主题为 dark,但是有一个 Button 组件,其需要特殊处理,就可以这样写,在 Button 内部再次 Provider 自己想要的主题即可,相同的 context 遵循就近原则。
lazy
延迟加载组件的工具,往往与 <Suspense> 组件一起使用。
简单使用:
js
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
接受参数
接受一个函数,返回 Promise 或者 其他类 thenable 的异步函数。React 默认不会去加载 lazy 包裹的组件,除非明确的在界面上需要渲染他。当开始加载时,React 会等待其解析,解析过程中由 Suspense 提供过渡响应,解析完毕后即可渲染。返回的 Promise 和 Promise 中 resolve 的值都会被缓存(比如打包的js文件),再次渲染就不会重复请求资源。但是这个组件本身的重渲染还是会被触发。如果该 Promise reject 请求,异常会冒泡至最近的处理函数(Error Boundary)抛出。
返回值
返回一个可以渲染在 fiber 树中的组件。
注意事项
- lazy 要在 js 模块顶层使用,不要在组件内部使用
使用案例
- 动态引入加载
js
const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview />
</Suspense>
效果:
加载中:
加载后:
加载一次后便不会再出现 loading
- 路由懒加载
介绍作者在工作中用过的一个使用 js 数组配置路由懒加载的案例:
jsx
// route.js
const Loadable = (Component) => (props) => (
<Suspense fallback={<Loader />}>
<Component {...props} />
</Suspense>
);
const Home = Loadable(lazy(() => import('views/pages')));
const User = Loadable(lazy(() => import('views/pages/common/user')));
const routes = [
{
path: 'home',
children: [
{
path: '/',
element: <Home />
}
]
},
{
path: 'setting',
children: [
{
path: 'user-setting',
element: <User />
}
]
}
]
useRoutes(routes);
// 使用
import Routes from 'route.js';
<Routes />
完 !