React 钩子使用状态在上下文提供程序中设置多个状态



我有一个createContext组件,它使用useState来设置从fetch函数返回的多个值。但是,在下面的代码中,当一个状态更新时,其他状态将返回到原始值。

例如,在getCountryCode()中,状态会针对countryCode进行更新,但随后iconCodeweatherInit()获取其值并countryCode返回到原始US

import React, { createContext, useState, useEffect } from 'react';
export const GlobalConsumer = createContext();
export const GlobalProvider = ({ children }) => {
const [state, setState] = useState({
menuPanel: false,
countryCode: 'US',
weatherLoading: true,
iconCode: '',
fahrenheit: '',
celcius: '',
showCelcius: false
});
const getCountryCode = () => {
const url = `https://ipapi.co/json/`;
fetch(url)
.then(data => data.json())
.then(data => {
const countryCode = data.country;
setState({ ...state, countryCode });
});
};
const weatherInit = () => {
const CITY_LAT = '...';
const CITY_LON = '...';
const OW_KEY = '...';
const url = `//api.openweathermap.org/data/2.5/weather?lat=${CITY_LAT}&lon=${CITY_LON}&units=imperial&appid=${OW_KEY}`;
fetch(url)
.then(data => data.json())
.then(data => {
const iconCode = data.weather[0].id;
setState({ ...state, iconCode });
const fahrenheit = Math.round(data.main.temp_max);
setState({ ...state, fahrenheit });
const celcius = Math.round((5.0 / 9.0) * (fahrenheit - 32.0));
setState({ ...state, celcius });
setTimeout(() => {
setState({ ...state, weatherLoading: false });
}, 150);
});
};
useEffect(() => {
getCountryCode();
weatherInit();
}, []);
return (
<GlobalConsumer.Provider
value={{
contextData: state,
togglemMenuPanel: () => {
setState({ ...state, menuPanel: !state.menuPanel });
},
toggleCelcius: () => {
setState({ ...state, showCelcius: !state.showCelcius });
}
}}
>
{children}
</GlobalConsumer.Provider>
);
};

我相信这是因为每个value都需要自己的useState。但是,是否可以合并这些值,或者是否有其他方法可以实现此结果,其中我只需要作为data传递给提供程序上下文

这是因为您在调用setState()时使用的是旧的state值。如此处所述(向下滚动到"Note"块(,您必须将函数传递给setState调用:

const iconCode = data.weather[0].id;
setState(prevState => ({ ...prevState, iconCode }));
const fahrenheit = Math.round(data.main.temp_max);
setState(prevState => ({ ...prevState, fahrenheit }));
const celcius = Math.round((5.0 / 9.0) * (fahrenheit - 32.0));
setState(prevState => ({ ...prevState, celcius }));
setTimeout(() => {
setState(prevState => ({ ...prevState, weatherLoading: false }));
}, 150);

与类组件中的 setState 方法不同,useState 不会自动合并更新对象。您可以通过将函数更新程序表单与对象传播语法相结合来复制此行为:

setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues};
});

相关内容

  • 没有找到相关文章

最新更新