通常情况下,我们通过props将参数从父组件传递给子组件,达到组件间状态参数共享的目的。但是面对嵌套了多层组件的情况,继续使用props一层一层的传递参数是非常冗余和繁琐的。
对于这种包含多层组件的传参,React提供了 Context 能力来支持父组件向它包含的无论嵌套层级有多深的子组件传递状态参数,让状态共享变的简单。
通过 createContext
创建Context对象,并且将其从定义Context的文件中导出,这样其他组件才能使用这个 Context;
createContext
函数有一个必填参数,这个参数是 context
对象初始化的默认值,这个参数可以传入任何类型的值。
// context.ts
import { createContext } from 'react';
export const RootContext = createContext({name:'levenx'});
在需要共享状态的最高层级的父组件外层包裹 context provider,这样它包含的所有子组件都可以使用 context
中的状态
import { RootContext } from './context.js';
import { useState } from 'react'
export default function Root({ level, children }) {
const [userInfo, setUserInfo] = useState({name:'levenx'});
return (
<RootContext.Provider value={userInfo}>
<section className="section">
{children}
</section>
</RootContext.Provider>
);
}
在Root组件上包裹 Context Provider
后,Root
组件中的所有子组件都能够通过 RootContext
获取userInfo信息。
在子组件中引入已经注册好的 context
并且通过 useContext
hook来消费共享的状态参数;
import { useContext } from 'react'
import { RootContext } from './context.js'
export default function Heading({ children }) {
const userInfo = useContext(RootContext);
// ...
return <div>{userInfo.name}</div>
}
useContext
是React内置的Hook,使用它可以从Context中读取状态,当 Context
状态发生变化时,useContext
读取的状态也会随之变化。
💡 并不是所有场景都适合使用 context,很多时候项目中很容易过度使用它。
context 相较于props从代码阅读角度而言,并不是那么清晰明了,通过props传递的参数,在传递时能够清晰知道传递了什么,context的话,需要从多个文件中梳理逻辑。
比如应用支持用户自定义显示主题,对于应用中所有的子组件都需要动态支持变化,这种非业务性的状态就可以通过 Context 进行管理。
随着应用业务的增长与迭代,最终全局共用的状态会越来越多,通过props处理就更加复杂了。这个时候就可以通过 reducer
和 context
配合使用来管理复杂的状态。
React Context 为了我们提供了一种组件间状态共享的手段,合理使用会高效提升代码运行效率和维护成本。后续会继续分享在生产项目中使用案例。