React 无法更新状态

时间:2021-07-11 09:59:56

标签: javascript reactjs react-hooks react-state

我不知道为什么我不能更新我的状态(请参阅 setCoords)。请求返回 200 代码并且我尝试检索的元素存在:enter image description here

这是我的代码:

let values = Array(24).fill(0);

感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

需要注意的一点是,不要将 awaitthen 混合使用(更多信息:Can await and then be mixed in one implementation?)。由于您使用的是 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("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>

答案 2 :(得分:0)

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