[英]React hooks useState to set multiple states in context provider
I have a createContext
component that is using useState
to set multiple values returned from a fetch
function.我有一个
createContext
组件,它使用useState
来设置从fetch
函数返回的多个值。 However in my code below, when a state is updated, the others states return to the original value.但是在我下面的代码中,当一个状态更新时,其他状态会返回到原始值。
For example, in getCountryCode()
the state is updated for countryCode
, but then iconCode
in weatherInit()
fetches its value and countryCode
returns to the original US
.例如,在
getCountryCode()
中, countryCode
的状态被更新,但是weatherInit()
iconCode
获取了它的值,而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>
);
};
I believe that this is caused because each value
requires it's own useState
.我相信这是因为每个
value
需要它自己的useState
。 However, can these values be merged or is there another way to achieve this outcome, where I am only required to pass as data
to the Provider context ?但是,这些值可以合并还是有另一种方法来实现这一结果,我只需要将
data
作为data
传递给Provider 上下文?
It's because you are using the old value of state
when calling setState()
.这是因为您在调用
setState()
时使用了旧的state
值。 As documented here (Scroll down to the "Note"-block) you have to pass a function to your setState
call:如此处所述(向下滚动到“注意”块),您必须将函数传递给
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);
Unlike the setState method found in class components, useState does not automatically merge update objects.
与类组件中的 setState 方法不同,useState 不会自动合并更新对象。 You can replicate this behavior by combining the function updater form with object spread syntax:
您可以通过将函数更新程序形式与对象传播语法相结合来复制此行为:
setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues};
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.