我正在尝试学习钩子(Hook),而useState
方法使我感到困惑。我正在将初始值分配给数组形式的状态。即使使用useState
或spread(...)
,without spread operator
中的set方法对我也不起作用。
我已经在另一台PC上创建了一个API,该API正在调用并获取要设置为状态的数据。
这是我的代码:
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<script src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<script type="text/babel">
// import React, { useState, useEffect } from "react";
// import ReactDOM from "react-dom";
const { useState, useEffect } = React; // web-browser variant
const StateSelector = () => {
const initialValue = [
{
category: "",
photo: "",
description: "",
id: 0,
name: "",
rating: 0
}
];
const [movies, setMovies] = useState(initialValue);
useEffect(() => {
(async function() {
try {
// const response = await fetch("http://192.168.1.164:5000/movies/display");
// const json = await response.json();
// const result = json.data.result;
const result = [
{
category: "cat1",
description: "desc1",
id: "1546514491119",
name: "randomname2",
photo: null,
rating: "3"
},
{
category: "cat2",
description: "desc1",
id: "1546837819818",
name: "randomname1",
rating: "5"
}
];
console.log("result =", result);
setMovies(result);
console.log("movies =", movies);
} catch (e) {
console.error(e);
}
})();
}, []);
return <p>hello</p>;
};
const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);
</script>
setMovies(result)
和setMovies(...result)
不起作用。可以在这里使用一些帮助。我希望将结果变量插入movies数组中。
最佳答案
与通过扩展React.Component
或React.PureComponent
创建的Class组件中的setState一样,使用useState
钩子(Hook)提供的更新程序进行的状态更新也是异步的,不会立即反射(reflect)出来。
另外,这里的主要问题不仅是异步性质,而且函数根据状态的当前闭包使用状态值,并且状态更新将反射(reflect)在下一次重新渲染中,现有闭包不会受到影响,这是一个事实,但是创建新的。现在,在当前状态下,挂钩中的值由现有的闭包获取,并且当重新渲染发生时,将根据是否再次创建函数来更新闭包。
即使您添加了setTimeout
函数,尽管超时将在发生重新渲染的一段时间后运行,但setTimeout
仍将使用其先前关闭操作的值,而不是更新后的值。
setMovies(result);
console.log(movies) // movies here will not be updated
如果要对状态更新执行操作,则需要使用useEffect钩子(Hook),就像在类组件中使用componentDidUpdate
一样,因为useState返回的setter没有回调模式useEffect(() => {
// action on update of movies
}, [movies]);
就更新状态的语法而言,setMovies(result)
会将状态中的先前movies
值替换为异步请求中可用的值。但是,如果要将响应与先前存在的值合并,则必须使用状态更新的回调语法以及正确使用的扩展语法,例如
setMovies(prevMovies => ([...prevMovies, ...result]));
关于javascript - useState设置方法不能立即反射(reflect)更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54069253/