React中解构useContext对象:避免重复调用weather.weather及类型错误解决
优化useContext解构写法避免重复调用
我目前使用useContext可正常导入数据,但需重复书写weather.weather才能获取具体值,希望通过解构变量避免重复调用。现有代码运行正常,仅需优化写法。
上下文导出代码
import { createContext, useState, useEffect } from 'react'; import { Weather } from '../../types'; import axios from 'axios'; import { WeatherContextType, WeatherContextProviderProps } from '../../types'; export const WeatherContext = createContext<WeatherContextType | null>(null); export const WeatherContextProvider = ({ children }: WeatherContextProviderProps) => { const [weather, setWeather] = useState<Weather | null>(); const fetchWeatherData = async () => { const response = await axios.get('http://mock-api-call/weather/get-weather'); setWeather(response.data.result.weather); }; useEffect(() => { fetchWeatherData(); }, []); return ( <WeatherContext.Provider value={{ weather, setWeather }}>{children}</WeatherContext.Provider> ); };
数据导入组件代码
import { WeatherContext } from './context/WeatherContext'; import { Title, Text, Container } from '@mantine/core'; import { useContext } from 'react'; const WeatherComponent = () => { const weather = useContext(WeatherContext); console.log(weather); return ( <Container style={{ width: '100%' }}> <Title order={2}>Today's Weather</Title> <Text size="lg"> {weather?.weather?.forcast} with a low of {weather?.weather?.min} and a high of{' '} {weather?.weather?.max} </Text> <Text size="md" data-testid="description"> {weather?.weather?.description} </Text> </Container> ); }; export default WeatherComponent;
尝试的解构方式及报错
我尝试直接解构:
const {weather} = useContext(WeatherContext);
但出现TypeScript错误:
Property 'weather' does not exist on type 'WeatherContextType | null'.
相关类型定义
export type WeatherContextType = { weather: Weather | null | undefined; setWeather: React.Dispatch<React.SetStateAction<Weather | null | undefined>>; };
解决方案
原因分析
报错是因为useContext(WeatherContext)返回的类型是WeatherContextType | null,TypeScript不允许直接解构可能为null的值;同时当前组件里的变量名weather和Context里的weather属性重名,也容易混淆。
方案1:兜底空对象+重命名解构
在解构时先用?? {}处理null的情况,同时重命名Context里的weather属性避免变量名冲突:
const WeatherComponent = () => { // 用weatherData重命名Context中的weather属性,同时兜底空对象避免解构null报错 const { weather: weatherData } = useContext(WeatherContext) ?? {}; return ( <Container style={{ width: '100%' }}> <Title order={2}>Today's Weather</Title> <Text size="lg"> {weatherData?.forcast} with a low of {weatherData?.min} and a high of{' '} {weatherData?.max} </Text> <Text size="md" data-testid="description"> {weatherData?.description} </Text> </Container> ); };
方案2:自定义Hook封装(更推荐)
封装一个自定义Hook,确保Context不为null,同时直接返回解构后的可用数据,组件里无需重复处理null:
- 在WeatherContext文件中添加自定义Hook:
import { useContext } from 'react'; import { WeatherContext } from './WeatherContext'; export const useWeather = () => { const context = useContext(WeatherContext); // 如果组件未在Provider内使用,抛出错误提示 if (!context) { throw new Error('useWeather must be used within a WeatherContextProvider'); } return context; };
- 在组件中使用:
import { useWeather } from './context/WeatherContext'; import { Title, Text, Container } from '@mantine/core'; const WeatherComponent = () => { // 直接解构Context中的weather属性,此时已确保context不为null const { weather } = useWeather(); return ( <Container style={{ width: '100%' }}> <Title order={2}>Today's Weather</Title> <Text size="lg"> {weather?.forcast} with a low of {weather?.min} and a high of{' '} {weather?.max} </Text> <Text size="md" data-testid="description"> {weather?.description} </Text> </Container> ); };
方案3:进一步解构Weather对象
如果想彻底避免weather?.xxx的写法,可以在组件里进一步解构Weather对象(注意处理undefined/null):
const WeatherComponent = () => { const { weather } = useWeather(); // 解构Weather对象的属性,兜底空对象避免报错 const { forcast, min, max, description } = weather ?? {}; return ( <Container style={{ width: '100%' }}> <Title order={2}>Today's Weather</Title> <Text size="lg"> {forcast} with a low of {min} and a high of {max} </Text> <Text size="md" data-testid="description"> {description} </Text> </Container> ); };
内容的提问来源于stack exchange,提问作者meWho
相关产品推荐
相关产品推荐

