React 无法更新状态 [英] React cannot update state

查看:20
本文介绍了React 无法更新状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么我不能更新我的状态(参见 setCoords).请求返回 200 代码,并且我尝试检索的元素存在:

这是我的代码:

const App = () =>{const [city, setCity] = useState("");const [forecast, setForecast] = useState(null);const [coords, setCoords] = useState({});const handleSearchChange = ev =>{设置城市(ev.target.value);};异步函数 onSearch() {如果(城市){等待 apiGet(`/geo/1.0/direct?q=${city}`).then(r => r.json()).then(r => setCoords({lat: r[0].lat, lon:r[0].lon}));//不设置任何东西await console.log(coords)//控制台日志 {}等待 apiGet(`/data/2.5/onecall?lat=${coords.lat}&lon=${coords.lon}&exclude=current,minutely,hourly,alerts`).then(r => r.json()).then(r => setForecast(r));}}

感谢您的帮助!

解决方案

需要注意的一点是不要将 awaitthen 混用(更多相关信息:可以等待然后混合在一个实现中吗?).由于您使用的是 async,我建议您将所有更改为 await,如下所示

另一件需要注意的是 setStates 调用(即 setCoordssetForecastsetCity)是 异步本质上意味着在设置状态后立即console.log记录刚刚更新的值.相反,React 会将这些 setState 安排到下一个渲染上——因此,您只能在下一个渲染周期中查看/访问最新的值.如果您想记录值,您可以将它们放在 HTML 中的 <pre> 标签内,或者在开头执行 console.log,如下所示:

const App = () =>{const [city, setCity] = useState("");const [forecast, setForecast] = useState(null);const [coords, setCoords] = useState({});console.log(城市",城市,预测",预报,坐标",坐标);const handleSearchChange = ev =>{设置城市(ev.target.value);};异步函数 onSearch() {如果(城市){const resNonJson = await apiGet(`/geo/1.0/direct?q=${city}`)const resJson = 等待 resNonJson.json())const item = resJson[0];setCoords({lat: item.lat, lon: item.lon}));//注意`setState` 是异步的,所以console.log 不会得到刚刚更新的值控制台日志(坐标)//{}console.log(item)//{lat:..., lon:...}const resNonJson2 = 等待 apiGet(`/data/2.5/onecall?lat=${item.lat}&lon=${item.lon}&exclude=current,minutely,hourly,alerts`)const resJson2 = 等待 resNonJson2.json())设置预测(resJson2);}}...(我相信你做的其他代码是正确的)返回 

<pre>{JSON.stringify(coords)}</pre>

I can't figure why I can't update my state (see setCoords). The request returns with a 200 code and the elements I'm trying to retrieve exists :

Here is my code :

const App = () => {
    const [city, setCity] = useState("");
    const [forecast, setForecast] = useState(null);
    const [coords, setCoords] = useState({});

    const handleSearchChange = ev => {
        setCity(ev.target.value);
    };

    async function onSearch() {
        if (city) {
            await apiGet(`/geo/1.0/direct?q=${city}`)
                .then(r => r.json())
                .then(r => setCoords({lat: r[0].lat, lon:r[0].lon})); // doesn't't set anything

            await console.log(coords) // console logs {}
            await apiGet(
                `/data/2.5/onecall?lat=${coords.lat}&lon=${coords.lon}&exclude=current,minutely,hourly,alerts`
            )
                .then(r => r.json())
                .then(r => setForecast(r));
        }
    }

Thanks for your help!

解决方案

One thing to note is that don't mix await with then (More on this: Can await and then be mixed in one implementation?). Since you are using async, I recommend you change all to await, like below

Another thing to note is setStates calls (i.e setCoords and setForecast and setCity) is asynchronous by nature, meaning that an immediate console.log after setting state will not log the just-updated value. Instead, React will schedule those setState onto the next render - therefore, you can only see/access the most updated values in the next render cycle. If you want to log values, you can put them as inside a <pre> tag in your HTML, or do console.log at the beginning, like below:

const App = () => {
    const [city, setCity] = useState("");
    const [forecast, setForecast] = useState(null);
    const [coords, setCoords] = useState({});

    console.log("City", city, "Forecast", forecast, "Coords", coords);

    const handleSearchChange = ev => {
        setCity(ev.target.value);
    };

    async function onSearch() {
        if (city) {
            const resNonJson = await apiGet(`/geo/1.0/direct?q=${city}`)
            const resJson = await resNonJson.json())
            const item = resJson[0];
            setCoords({lat: item.lat, lon: item.lon}));

            // Note that `setState` is async so console.log will not get the just-updated value
            console.log(coords) // {}
            console.log(item) // {lat:..., lon:...}
            const resNonJson2 = await apiGet(
                `/data/2.5/onecall?lat=${item.lat}&lon=${item.lon}&exclude=current,minutely,hourly,alerts`
            )
             const resJson2 = await resNonJson2.json())
             setForecast(resJson2);
        }
    }
    ... (other codes that I trust you do correctly)

    return <div>
    <pre>{JSON.stringify(coords)}</pre>
    </div>

这篇关于React 无法更新状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆