我正在努力学习钩子和钩子 useState
方法让我困惑。我以数组的形式为状态赋值。中的set方法 useState
即使和你在一起也不为我工作 spread(...)
或 without spread operator
. 我在另一台pc上制作了一个api,我正在调用它并获取我想要设置为状态的数据。
这是我的密码:
<div id="root"></div>
<script type="text/babel" defer>
// 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>
<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>
这个 setMovies(result)
以及 setMovies(...result)
它不起作用。我需要一些帮助。
我希望结果变量被推送到movies数组中。
13条答案
按热度按时间js5cn81o1#
使用后台定时器库解决我的问题https://github.com/ocetnik/react-native-background-timer
const timeoutId = BackgroundTimer.setTimeout(() => { // this will be executed once after 1 seconds // even when app is the the background console.log('tac'); }, 1000);
vkc1a9a22#
关闭并不是唯一的原因。
基于源代码的
useState
(简化如下)。在我看来,这个值永远不会马上赋值。发生的情况是,当您调用
setValue
. 在计划生效后,只有在到达下一个渲染时,这些更新操作才会应用于该状态。这意味着,即使我们没有闭包问题,也要对
useState
不会马上给你新的值。新值在下次渲染之前甚至不存在。还有一篇文章以类似的方式解释了上述内容,https://dev.to/adamklein/we-don-t-know-how-react-state-hook-works-1lp8
holgip5t3#
我发现了一个骗局
setState
钩子。不能使用旧变量。您必须创建新变量并将其传递给hook。例如:你只会看到
Ayşe
及Fatma
用户。因为你回来了(或路过)oldUsers
变量此变量的引用与旧状态的引用相同。必须返回新创建的变量。若您传递相同的引用变量,则reactjs不会更新状态。y4ekin9u4#
现在您应该看到,您的代码确实可以工作。不起作用的是
console.log(movies)
. 这是因为movies
指向旧的状态。如果你移动你的console.log(movies)
外useEffect
,右上方的返回,您将看到更新的电影对象。vpfxa7rd5#
useeffect有自己的状态/生命周期,它与状态的变化有关,只有在您在参数或效果中传递函数时,它才会更新。
只需在参数状态下传递一个参数,它就可以完美地工作。
holgip5t6#
有很多很好的答案可以说明如何修复代码,但是有一个npm包可以让您通过更改
import
. 它叫react usestateref就你而言:
如你所见。使用此库可以访问最新状态。
7z5jn7bk7#
使用my library中的自定义挂钩,您可以等待状态值更新:
useAsyncWatcher(...values):watcherFn(peekPrevValue: boolean)=>Promise
-是一个围绕useeffect的承诺 Package 器,它可以等待更新并返回一个新值,如果可选,还可能返回上一个值peekPrevValue
参数设置为true。(现场演示)
import React, { useCallback, useEffect } from "react";
import { useAsyncDeepState } from "use-async-effect2";
function TestComponent(props) {
const [state, setState] = useAsyncDeepState({
counter: 0,
computedCounter: 0
});
useEffect(() => {
setState(({ counter }) => ({
computedCounter: counter * 2
}));
}, [state.counter]);
const inc = useCallback(() => {
(async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
await setState(({ counter }) => ({ counter: counter + 1 }));
console.log("computedCounter=", state.computedCounter);
})();
});
return (
useAsyncDeepState demo
state.counter : {state.counter}
state.computedCounter : {state.computedCounter}
<button onClick={() => inc()}>Inc counter
);
}
mcvgt66p8#
var[state,setstate]=usestate(默认值)
useffect(()=>{var updatedstate setstate(currentstate=>{//不要通过获取更新状态updatestate=currentstate return currentstate}来更改状态)警报(updatestate)//当前状态。}
kq0g1dla9#
类似于通过扩展
React.Component
或React.PureComponent
,使用提供的更新程序进行状态更新useState
钩子也是异步的,不会立即反映出来。此外,这里的主要问题不仅仅是异步性质,而是函数根据其当前闭包使用状态值,并且状态更新将反映在下一次重新呈现中,其中现有闭包不受影响,而是创建新闭包。现在,在当前状态下,钩子中的值由现有闭包获得,当重新呈现时,闭包将根据是否重新创建函数进行更新。
即使你添加了一个
setTimeout
函数,虽然超时将在重新渲染发生的一段时间后运行,但setTimeout
仍将使用以前的闭包中的值,而不是更新的值。如果要在状态更新时执行操作,则需要使用useeffect挂钩,就像使用
componentDidUpdate
类内组件,因为usestate返回的setter没有回调模式就更新状态的语法而言,
setMovies(result)
将取代以前的movies
值与异步请求中可用的值处于同一状态。但是,如果要将响应与以前存在的值合并,则必须使用状态更新的回调语法以及正确使用扩展语法,如
sbtkgmzw10#
对上一答案的补充细节:
当React
setState
是异步的(类和钩子都是异步的),很容易用这个事实来解释观察到的行为,但这并不是它发生的原因。tldr:原因是围绕一个不可变的
const
价值解决方案:
读取渲染函数中的值(不在嵌套函数中):
将变量添加到依赖项中(并使用react hooks/deps eslint规则):
使用可变引用(当无法执行上述操作时):
解释发生的原因:
如果async是唯一的原因,那么
await setState()
.然而,两者
props
及state
假定在1次渲染期间保持不变。对待
this.state
好像它是不变的。对于钩子,通过将常量值与
const
关键词:该值在两个渲染之间可能不同,但在渲染本身和任何闭包内保持不变(即使在渲染完成后仍然有效的函数,例如。
useEffect
,事件处理程序,在任何承诺或设置超时内)。考虑仿冒,但同步,React类似的实施:
rqqzpn5f11#
您可以使用
useRef
钩子,但当它更新时,它不会重新渲染。我已经创建了一个名为usestateref的钩子,它可以从两个世界中为您带来好处。这就像更新组件时重新渲染的状态,就像“ref”始终具有最新值。请参见此示例:
它的工作原理一模一样
useState
但除此之外,它还提供了当前状态ref.current
了解更多信息:https://www.npmjs.com/package/react-usestateref
xdnvmnnf12#
我刚刚用usereducer完成了一个重写,在@kentcdobs文章(参考下面)之后,这篇文章给了我一个可靠的结果,它不会因为这些闭包问题而遭受任何损失。
见:https://kentcdodds.com/blog/how-to-use-react-context-effectively
我将他的可读性样板压缩到我喜欢的干燥程度——阅读他的沙盒实现将向您展示它实际上是如何工作的。
享受吧,我知道我是!!
使用与此类似的用法:
现在,在我的所有页面上,一切都很顺利
美好的
谢谢你,肯特!
zour9fqk13#
我发现这很好,而不是将状态(方法1)定义为,
const initialValue = 1;
const [state,setState] = useState(initialValue)
尝试这种方法(方法2),const [state = initialValue,setState] = useState()
这在不使用useeffect的情况下解决了重新渲染问题,因为我们不关心此案例的内部关闭方法。p、 如果您关心在任何用例中使用旧状态,那么需要使用usestate with useeffect,因为它需要具有该状态,所以在这种情况下应使用方法1。