React Hooks useContext
开发环境是React Native + Taro + Typescript,下面第一部分是父组件
import React, { useState } from 'react'
import { View, Text } from '@tarojs/components'
import AppContext, { Theme, User } from './Components/ComContext'
import ContextA from './Components/ContextA'
import ContextB from './Components/ContextB'
import ContextC from './Components/ContextC'
import styles from './index.module.scss'
import {HKText,HKView
} from 'hk-components';const UseContext: React.FC = () => {const [theme, setTheme] = useState<Theme>(Theme.LIGHT)const [user, setUser] = useState<User>({ name: '小明', age: 18 })const toggleTheme = () => {// 使用函数式更新,确保类型安全setTheme(currentTheme => currentTheme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT)}const updateUser = (newUser: User) => {setUser(newUser)}return (<AppContext.Provider value={{theme,toggleTheme,user,updateUser}}>{/* 注:如果在这个位置再多写一份AppContext.Provider,那么这个位置的provider的值会覆盖外层的,子组件也会获取覆盖后的值*/}<HKView className={styles.container}><Text className='title'>父组件</Text><Text>当前主题: {theme}</Text><Text>用户名: {user.name}</Text><Text>用户年龄: {user.age}</Text><View className={styles.showTextBox}><ContextA /><ContextB /></View><View><Text>在同一个子组件中,实现隔代组件间共享一份数据</Text><ContextC></ContextC></View></HKView></AppContext.Provider>)
}export default UseContext
下面的三部分为子组件:ContextA、ContextB、ContextC
import { View, Text, Button } from '@tarojs/components'
import AppContext from './ComContext'
import styles from './index.module.scss'
import {HKText,HKView
} from 'hk-components';const ContextA: React.FC = () => {const { theme, toggleTheme, user, updateUser } = useContext(AppContext)const handleIncreaseAge = () => {updateUser({ ...user, age: user.age + 1 })}return (<HKView className={styles.container}><View className={styles.showTextBox}><Text className={styles.showText}>ContextA 组件</Text><Text className={styles.showText}>当前主题: {theme}</Text><Text className={styles.showText}>用户名: {user.name}</Text><Text className={styles.showText}>用户年龄: {user.age}</Text></View><View className={styles.actionContainer}><Button className={styles.actionBox} onClick={toggleTheme}>切换主题</Button><Button className={styles.actionBox} onClick={handleIncreaseAge}>增加年龄</Button></View></HKView>)
}export default ContextA
import React, { useContext } from 'react'
import { View, Text, Button } from '@tarojs/components'
import AppContext from './ComContext'
import styles from './index.module.scss'
import {HKText,HKView
} from 'hk-components';const ContextB: React.FC = () => {const { theme, toggleTheme, user, updateUser } = useContext(AppContext)const handleToggleUser = () => {const newName = user.name === '小明' ? '小红' : '小明'updateUser({ ...user, name: newName })}return (<HKView className={styles.container}><View className={styles.showTextBox}><Text className={styles.showText}>ContextB 组件</Text><Text className={styles.showText}>当前主题: {theme}</Text><Text className={styles.showText}>用户名: {user.name}</Text><Text className={styles.showText}>用户年龄: {user.age}</Text></View><View className={styles.actionContainer}><Button className={styles.actionBox} onClick={toggleTheme}>切换主题</Button><Button className={styles.actionBox} onClick={handleToggleUser}>切换用户</Button></View></HKView>)
}export default ContextB
import React, { createContext, useContext, useState } from 'react';
import { View, Text, Button } from '@tarojs/components';
import {HKText,HKView
} from 'hk-components';// 创建Context
const MyContext = createContext<any>(null);// ContextC 父组件
const ContextC: React.FC = () => {const [count, setCount] = useState(0);const updateCount = (newCount: number) => {setCount(newCount);};const contextValue = {message: 'Hello from Context!',count,updateCount,user: {name: '张三',age: 25}};return (<MyContext.Provider value={contextValue}><View style={{ padding: 20, backgroundColor: '#f5f5f5',minHeight: '100vh'}}><Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 16 }}>ContextC 父组件</Text><Text style={{ marginBottom: 16 }}>当前计数: {count}</Text><ComXa /></View></MyContext.Provider>);
};// ComXa 子组件
const ComXa: React.FC = () => {return (<View style={{ padding: 16, backgroundColor: '#e3f2fd', margin: 10, borderRadius: 8}}><Text style={{ fontSize: 16, marginBottom: 12 }}>ComXa 子组件</Text><ComXe /></View>);
};// ComXe 孙子组件(使用useContext)
const ComXe: React.FC = () => {const context = useContext(MyContext);if (!context) {return (<View><Text>Context未找到</Text></View>);}const { message, count, updateCount, user } = context;const handleIncrement = () => updateCount(count + 1);const handleDecrement = () => updateCount(count - 1);return (<View style={{ padding: 16, backgroundColor: '#fff3e0', borderRadius: 8}}><Text style={{ fontSize: 16, fontWeight: 'bold', marginBottom: 8 }}>ComXe 孙子组件</Text><Text style={{ marginBottom: 8 }}>消息: {message}</Text><Text style={{ marginBottom: 8 }}>用户: {user.name} ({user.age}岁)</Text><Text style={{ marginBottom: 12 }}>计数: {count}</Text><View style={{ flexDirection: 'row', gap: 8 }}><Button onClick={handleDecrement}>减少</Button><Button onClick={handleIncrement}>增加</Button></View></View>);
};export default ContextC;
下面为类型推断的一些声明与export
import { createContext } from 'react'// 使用枚举方式定义主题,避免类型推断问题
export enum Theme {LIGHT = 'light',DARK = 'dark'
}export interface User {name: stringage: number
}export interface AppContextValue {theme: ThemetoggleTheme: () => voiduser: UserupdateUser: (user: User) => void
}// 创建 Context
const AppContext = createContext<AppContextValue>({theme: Theme.LIGHT,toggleTheme: () => {},user: { name: '', age: 0 },updateUser: () => {}
})export default AppContext