如何实现useContext (React Native, Expo)来控制天气单元设置?



我正在尝试使用useContext()钩子实现在英制和公制单位之间切换的能力。到目前为止,我还没有取得多大的成功。我已经阅读了React的useContext()文档并阅读了本文。这是我当前的JavaScript源代码,目前没有按预期运行:

App.js-上下文提供程序所在的位置

import React from 'react';
import WeatherScreen from './components/screens/WeatherScreen';
import { CurrentUnitContext } from './components/hooks/CurrentUnitContext.js';
export default App = () => { 

return ( 
<CurrentUnitContext.Provider
value={"imperial"}
>
<WeatherScreen />
</CurrentUnitContext.Provider>
);
};

CurrentUnitContext.js-用于createContext()

import { createContext } from 'react';
/**
* WIP custom hook for setting current unit
* 
* todo - change weather units here
* set imperial (F), metric (C), and maybe standard (K)
*/
export default CurrentUnitContext = createContext();
/**
export default CurrentUnitContext = createContext({
theCurrentUnit: "imperial",
setTheCurrentUnit: () => {},

});
*/

UnitSwitch.js-旨在包含组件设置与用户反馈的单位。

import React, { useState, useEffect, useContext } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { CurrentUnitContext } from '../../hooks/CurrentUnitContext.js';
import { tailwind, fontConfig } from '../../../tailwind.js';
/**
* Unit Switcher child component. Based on switch's boolean
* value useState hook isEnabled, set useEffect hook currentUnit
* to either "imperial" or "metric".
* 
* @param - switchHeader: Displays the unit switch header
* text passed from WeatherContent.js
* @param - imperialUnits: Text passed from WeatherContext.js for
* imperial unit button string.
* @param - metricUnits: Text passed from WeatherContext.js for
* metric unit button string.
*/
export default UnitSwitch = ({ imperialUnits, metricUnits, switchHeader }) => {
const [theCurrentUnitSetting, setTheCurrentUnitSetting] = useState("imperial");
return (
<View style={tailwind('bg-gray-300 border-t-2 p-3 w-64 h-48')}>
<Text style={tailwind('text-center text-22fz')}>
{switchHeader}
</Text>
<View style={tailwind('flex-1 justify-center items-center')}>
<TouchableOpacity
style={tailwind('')}
onPress={() => setTheCurrentUnitSetting("metric")}
>
<Text style={tailwind('')}>
{metricUnits}
</Text>
</TouchableOpacity>
</View>
</View>
);
};

getWeather.js-用于获取天气的钩子

import { useState, useEffect, useContext } from 'react';
import useLocation from '../hooks/useLocation.js';
import { CurrentUnitContext } from './CurrentUnitContext.js';
/**
* @getWeather - if permission was granted in useLocation() hook,
* uses Object theLocation containing lat. and long. coordinates as
* decimal number values. Returns the currentWeather. useEffect()
* relies on the value of Object theLocation.
*
* @WEATHER_API_KEY - accessed from clientSecret directory,
* hidden for repo security and must be manually provided.
* @currentWeather - useState hook to store JSON result of
* current weather data.
* @baseWeatherUrl - initial OpenWeatherMap API access string
* @weatherUrl - Full OpenWeatherMap API access string
*/
export default getWeather = () => {
const theLocation = useLocation();
const theCurrentUnit = useContext(CurrentUnitContext);
const [currentWeather, setCurrentWeather] = useState();
useEffect(() => {
const { WEATHER_API_KEY } = require("../clientSecret/openWeather.json");
let baseWeatherUrl = 'https://api.openweathermap.org/data/2.5/weather?', 
weatherUrl = "";
//console.log(theLocation); //confirm we are getting location, uncomment if needed
if (theLocation !== undefined) {
weatherUrl = `${baseWeatherUrl}lat=${theLocation.latitude}&lon=${theLocation.longitude}&units=${theCurrentUnit}&appid=${WEATHER_API_KEY}`;
console.log(weatherUrl); //uncomment if needed
const fetchWeather = async () => {
try {
const response = await fetch(weatherUrl);
const result = await response.json();
if (response.ok) {
setCurrentWeather(result);
} else {
alert(result.message);
};
} catch (error) {
console.log(error);
alert(error.message);

} finally {
console.log("async function fetchWeather() has been run."); //API rate call confirmation
};
};
//API calls must not occur more than once every minute.
fetchWeather();
};
}, [theLocation, theCurrentUnit]);
return currentWeather;
};
如现在所示,出现的错误消息是:

TypeError: undefined不是一个对象(求值>'_CurrentUnitContext.CurrentUnitContext.Provider')

此错误位于:在App中(由ExpoRoot创建)(在renderApplication.js:45)在RCTView中(at View.js:34)in View (at AppContainer.js:106)在RCTView中(at View.js:34)in View (at AppContainer.js:132)in AppContainer (at renderApplication.js:39)

我得到了帮助,在CurrentUnitContext.js中修改

export default CurrentUnitContext = createContext();

export let CurrentUnitContext = createContext();

修复错误。

最新更新