我试图学习钩子,而useState
方法让我感到困惑。我以数组的形式给一个状态赋值初始值。useState
中的set方法不适用于我,无论是否使用扩频运算符。
我在另一台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数组中。
我知道已经有很好的答案了。但我想给出另一个解决同样问题的方法,并使用我的模块react useStateRef访问最新的“电影”状态。
正如您所理解的,通过使用React状态,您可以在每次状态更改时呈现页面。但是通过使用React ref,您总是可以获得最新的值。
因此,模块react-useStateRef
允许您同时使用state's和ref's。它向下兼容React.useState
,因此您可以替换导入
语句
const { useEffect } = React
import { useState } from 'react-usestateref'
const [movies, setMovies] = useState(initialValue);
useEffect(() => {
(async function() {
try {
const result = [
{
id: "1546514491119",
},
];
console.log("result =", result);
setMovies(result);
console.log("movies =", movies.current); // will give you the latest results
} catch (e) {
console.error(e);
}
})();
}, []);
上一个答案的附加细节:
虽然React的setState
是异步的(包括类和钩子),并且很容易用这个事实来解释观察到的行为,但这并不是它发生的原因。
TLDR:原因是围绕不可变的const
值的闭包范围。
>
useEffect(() => { setMovies(result) }, [])
console.log(movies)
将变量添加到依赖项中(并使用react hooks/deps eslint规则):
useEffect(() => { setMovies(result) }, [])
useEffect(() => { console.log(movies) }, [movies])
使用临时变量:
useEffect(() => {
const newMovies = result
console.log(newMovies)
setMovies(newMovies)
}, [])
使用可变引用(如果我们不需要状态,只想记住值-更新引用不会触发重新渲染):
const moviesRef = useRef(initialValue)
useEffect(() => {
moviesRef.current = result
console.log(moviesRef.current)
}, [])
如果异步是唯一的原因,则可以等待setState()。
但是,假定道具
和状态
在1次渲染期间不变。
将此.state
视为是不可变的。
对于钩子,通过使用带有const
关键字的常量值来增强这个假设:
const [state, setState] = useState('initial')
2个渲染之间的值可能不同,但在渲染本身和任何闭包中保持不变(即使在渲染完成后,函数的寿命也会更长,例如,事件处理程序,任何Promise或setTimeout中的函数)。
考虑以下假的,但同步的,类似React的实现:
// sync implementation:
let internalState
let renderAgain
const setState = (updateFn) => {
internalState = updateFn(internalState)
renderAgain()
}
const useState = (defaultState) => {
if (!internalState) {
internalState = defaultState
}
return [internalState, setState]
}
const render = (component, node) => {
const {html, handleClick} = component()
node.innerHTML = html
renderAgain = () => render(component, node)
return handleClick
}
// test:
const MyComponent = () => {
const [x, setX] = useState(1)
console.log('in render:', x) // ✅
const handleClick = () => {
setX(current => current + 1)
console.log('in handler/effect/Promise/setTimeout:', x) // ❌ NOT updated
}
return {
html: `<button>${x}</button>`,
handleClick
}
}
const triggerClick = render(MyComponent, document.getElementById('root'))
triggerClick()
triggerClick()
triggerClick()
<div id="root"></div>
很像通过扩展React创建的Class组件中的setState。组件
或React。PureComponent
,使用useState
钩子提供的更新器的状态更新也是异步的,不会立即反映。
此外,这里的主要问题不仅仅是异步性质,而是函数根据其当前闭包使用状态值,并且状态更新将反映在下一次重新呈现中,其中现有闭包不受影响,而是创建新闭包。现在,在当前状态下,钩子中的值由现有闭包获得,当重新呈现时,闭包将根据是否重新创建函数进行更新。
即使在函数中添加了一个setTimeout
,尽管超时将在重新渲染发生的一段时间后运行,但setTimeout
仍将使用其上一个闭包的值,而不是更新的值。
setMovies(result);
console.log(movies) // movies here will not be updated
如果你想在状态更新上执行一个操作,你需要使用use效应钩子,就像在类组件中使用组件diUpdate
一样,因为useState返回的setter没有回调模式
useEffect(() => {
// action on update of movies
}, [movies]);
就更新状态的语法而言,setMovies(result)
将用异步请求中可用的值替换状态中以前的movies
值。
但是,如果您想将响应与以前存在的值合并,您必须使用状态更新的回调语法以及正确使用扩展语法,如
setMovies(prevMovies => ([...prevMovies, ...result]));
我正在尝试学习挂钩,方法让我感到困惑。我正在以数组的形式为状态分配初始值。中的set方法不适合我,无论是否使用扩展语法。 我在另一台PC上制作了一个API,我正在调用并获取我想要设置为状态的数据。 这是我的代码: 无论是设置电影(结果)还是设置电影(结果)都不起作用。 我希望将
问题内容: 我正在尝试学习钩子,该方法使我感到困惑。我正在将初始值分配给数组形式的状态。即使使用或,in中的set方法对我也不起作用。我已经在另一台PC上创建了一个API,该API正在调用并获取要设置为状态的数据。 这是我的代码: 的以及不工作。可以在这里使用一些帮助。 我希望将结果变量推入movies数组中。 问题答案: 类似于通过扩展或创建的Class组件中的setState,使用钩子提供的更
每当我使用useState设置变量时,该值不会立即反映出来。这里我有一个useEffect调用computePriceSummary(); computePriceSummary调用三个函数,如图所示: 这些函数使用useState设置变量: 浏览器中显示的值包括: Stackoverflow中的解决方案建议使用useEffect跟踪变量,因此我做了: 结果还是一样。
问题内容: 我正在做一个待办事项应用程序。这是违规代码的非常简化的版本。我有一个复选框: 这是调用复选框的函数: updateItem是映射为分派到redux的函数 我的问题是,当我调用updateItem操作并在console.log状态时,它总是落后1步。如果未选中该复选框且该复选框不为true,则仍将状态为true传递给updateItem函数。我是否需要调用另一个函数来强制状态更新? 问题
我正在尝试在react中开发todo应用程序。下面是代码。 当我在文本框中输入todo并单击添加时,todo将给出旧值。 例如,如果我输入“a”,则todo数组将给出,然后当我输入“b”时,todo显示。请帮忙。 编辑: 下面的工作
下面是我的代码的一个片段。调用filteredData()时,状态未更新。在状态更新之前,我必须单击按钮两次。这是一个旧项目,我正在使用钩子更新它。我以前在设置状态后使用了回调函数,但我不能用钩子实现。 }