简体   繁体   English

React 无法更新状态

[英]React cannot update state

I can't figure why I can't update my state (see setCoords).我不知道为什么我不能更新我的状态(请参阅 setCoords)。 The request returns with a 200 code and the elements I'm trying to retrieve exists :请求返回一个 200 代码,我试图检索的元素存在: 在此处输入图片说明

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!谢谢你的帮助!

try useCallback尝试使用回调

... 
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]);
... 

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

One thing to note is that don't mix await with then (More on this: Can await and then be mixed in one implementation? ).需要注意的一件事是,不要将awaitthen混合(更多相关信息: 可以将 await 然后混合在一个实现中吗? )。 Since you are using async , I recommend you change all to await , like below由于您使用的是async ,我建议您将 all 更改为await ,如下所示

Another thing to note is setStates calls (ie 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.另一件要注意的事情是setStates调用(即setCoordssetForecastsetCity )本质上是异步的,这意味着设置状态后的即时console.log不会记录刚刚更新的值。 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.相反,React 会将这些 setState 安排到下一次渲染 - 因此,您只能在下一个渲染周期中查看/访问最新更新的值。 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:如果要记录值,可以将它们放在 HTML 中的<pre>标记中,或者在开头执行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>

setState() operation is asynchronous in React. setState()操作在 React 中是异步的。 All that means that you can't rely on your new state values you apply in setState to be applied immediately.所有这一切都意味着您不能依赖在 setState 中应用的新状态值立即应用。 Along with setState, fetch() is also asynchronous in nature.Hence, console.log statement will not wait for the setState() or fetch() to get executed.与 setState 一样, fetch()本质上也是异步的。因此,console.log 语句不会等待 setState() 或 fetch() 执行。 In such a scenario, you can always handle it by a callback argument of setState().在这种情况下,您始终可以通过 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}))

       

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM