React hooks - useContext
useContext
- 用法
- 使用
- 以非侵入的方式使用 Context
- 使用 useContext 重构 useReducer 案例
用法
实现多层组件的数据传递
(图片来源网络,侵删)- 在全局创建 Context 对象
- 在父组件中使用 Context.Provider 提供数据
- 在子组件中使用 useContext 使用数据
import React, { useContext } from 'react' // 全局 const MyContext = React.createContext(初始数据)
// 父组件 const Father = () => { return {name: 'escook', age: 22}} }
// 子组件 const Son = () => { const myCtx = useContext(MyContext) return
姓名:{myCtx.name}
年龄:{MyCtx.age}
使用
// 声明 TS 类型 type ContextType = { count: number; setCount: React.Dispatch } // 1. 创建 Context 对象 const AppContext = React.createContext({} as ContextType)
export const LevelA: React.FC = () => { // 定义状态 const [count, setCount] = useState(0) return ( { padding: 30, backgroundColor: 'lightblue', width: '50vw' }}
count值是:{count}
() = setCount((prev) => prev + 1)}>+1 {/* 2. 使用 Context.Provider 向下传递数据 */} { count, setCount }} {/* 使用子组件 */} ) }export const LevelB: React.FC = () => { return ( { padding: 30, backgroundColor: 'lightgreen' }} {/* 使用子组件 */} ) }
export const LevelC: React.FC = () => { // 3. 使用 useContext 接收数据 const ctx = useContext(AppContext) return ( { padding: 30, backgroundColor: 'lightsalmon' }} {/* 4. 使用 ctx 中的数据和方法 */}
count值是:{ctx.count}
() = ctx.setCount((prev) => prev + 1)}>+1 () = ctx.setCount(0)}>重置 ) }以非侵入的方式使用 Context
保证父组件中代码的单一性和Provider的通用性,解决父组件中侵入了 的问题,
Context.Provider 封装到独立的 Wrapper 函数式组件中。
核心思路:每个 Context 都创建一个对应的 Wrapper 组件,在 Wrapper 组件中使用 Provider 向 children 注入数据。
// 声明 TS 类型 type ContextType = { count: number; setCount: React.Dispatch } // 创建 Context 对象 const AppContext = React.createContext({} as ContextType)
// 定义独立的 Wrapper 组件,被 Wrapper 嵌套的子组件会被 Provider 注入数据 export const AppContextWrapper: React.FC = (props) => { // 1. 定义要共享的数据 const [count, setCount] = useState(0) // 2. 使用 AppContext.Provider 向下共享数据 return { count, setCount }}{props.children} }
import React from 'react' import { AppContextWrapper, LevelA } from '@/components/use_context/01.base.tsx' const App: React.FC = () => { return ( ) } export default App
组件树的嵌套关系为:App => Wrapper => LevelA => LevelB => LevelC。因此在 LevelA、LevelB 和 LevelC 组件中,都可以使用 context 中的数据。
export const LevelA: React.FC = () => { // 使用 useContext 接收数据 const ctx = useContext(AppContext) return ( { padding: 30, backgroundColor: 'lightblue', width: '50vw' }} {/* 使用 ctx 中的数据和方法 */}
count值是:{ctx.count}
() = ctx.setCount((prev) => prev + 1)}>+1 ) }export const LevelC: React.FC = () => { // 使用 useContext 接收数据 const ctx = useContext(AppContext) return ( { padding: 30, backgroundColor: 'lightsalmon' }} {/* 使用 ctx 中的数据和方法 */}
count值是:{ctx.count}
() = ctx.setCount((prev) => prev + 1)}>+1 () = ctx.setCount(0)}>重置 ) }使用 useContext 重构 useReducer 案例
// 1. 定义 Context 的 TS 类型 // 在这一步,我们必须先明确要向子组件注入的数据都有哪些 type UserInfoContextType = { user: UserType; dispatch: React.Dispatch } // 2. 创建 Context 对象 const UserInfoContext = React.createContext({} as UserInfoContextType)
// 3. 创建 ContextWrapper 组件 export const UserInfoContextWrapper: React.FC = ({ children }) => { const [state, dispatch] = useImmerReducer(reducer, defaultState, initAction) return { user: state, dispatch }}{children} }
import React from 'react' import { UserInfoContextWrapper, Father } from '@/components/use_reducer/01.base.tsx' const App: React.FC = () => { return ( ) } export default App
export const Father: React.FC = () => { // 4. 调用 useContext 导入需要的数据 const { user: state, dispatch } = useContext(UserInfoContext) const changeUserName = () => dispatch({ type: 'UPDATE_NAME', payload: '刘龙彬' }) return (
changeUserName}修改用户名) }{JSON.stringify(state)}
{/* 5. 这里没有必要再往子组件传递 props 了 */} {/* */}const Son1: React.FC = () => { // 6. 把 props 替换为 useContext() 的调用 const { dispatch, user } = useContext(UserInfoContext) const add = () => dispatch({ type: 'INCREMENT', payload: 1 }) return (
{JSON.stringify(user)}
add}年龄+1const Son2: React.FC = () => { // 7. 把 props 替换为 useContext() 的调用 const { dispatch, user } = useContext(UserInfoContext) const sub = () => dispatch({ type: 'DECREMENT', payload: 5 }) return (
{JSON.stringify(user)}
sub}年龄-5const GrandSon: React.FC = () => { // 8. 把 props 替换为 useContext() 的调用 const { dispatch } = useContext(UserInfoContext) const reset = () => dispatch({ type: 'RESET' }) return (
这是 GrandSon 组件
reset}重置 ) }
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。