开发环境是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: string
age: number
}
export interface AppContextValue {
theme: Theme
toggleTheme: () => void
user: User
updateUser: (user: User) => void
}
// 创建 Context
const AppContext = createContext<AppContextValue>({
theme: Theme.LIGHT,
toggleTheme: () => {},
user: { name: '', age: 0 },
updateUser: () => {}
})
export default AppContext