react无法更新状态

rur96b6h  于 2021-09-13  发布在  Java
关注(0)|答案(3)|浏览(370)

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

这是我的密码:

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));
        }
    }

谢谢你的帮助!

sf6xfgos

sf6xfgos1#

需要注意的一点是,不要混淆 await 具有 then (更多信息:可以等待,然后在一个实现中混合使用吗?)。因为你正在使用 async ,我建议您将所有更改为 await ,如下图所示
另一件需要注意的事情是 setStates 电话(即 setCoordssetForecastsetCity )本质上是异步的,这意味着 console.log 设置后,状态不会记录刚刚更新的值。相反,react会将这些设置状态安排到下一个渲染上-因此,您只能在下一个渲染周期中查看/访问最新的值。如果要记录值,可以将它们放在 <pre> 在html中添加标记,或者 console.log 开始时,如下所示:

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>
z8dt9xmd

z8dt9xmd2#

尝试使用回调

... 
const onSearch = useCallback(async () {
        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));
        }
    }, [coords]);
...

参考:https://reactjs.org/docs/hooks-reference.html#usecallback

ecr0jaav

ecr0jaav3#

setstate()操作在react中是异步的。所有这一切都意味着您不能依赖于您在setstate中应用的新状态值来立即应用。与setstate一起,fetch()本质上也是异步的。因此,console.log语句不会等待setstate()或fetch()执行。在这种情况下,始终可以通过setstate()的回调参数来处理它。

await apiGet(`/geo/1.0/direct?q=${city}`)
            .then(r => r.json())
            .then(r => setCoords(data => {lat: r[0].lat, lon:r[0].lon}))

相关问题