在使用useState和useReducer钩子时,我意识到一个问题,即更新状态函数(setState,dispatch)之后的任何代码行都将在下一次重新呈现时被调用(更新之前的状态)。这意味着更新状态函数会导致立即重新渲染,而不是等待整个函数执行。
const [aaa, setAAA] = useState<boolean>(false);
const updateMyBiddingList = async (atDate?: string) => {
try {
console.log('step 0');
const result = await getBiddingCartFromService(atDate ? atDate : myBiddingListState.myBiddingList[0].updatedAt);
if (result.responseCode.toString().startsWith('2')) {
setAAA(true);
console.log('step 1');
}
console.log('step 2 ', aaa);
}
catch (err) {
if (timeOut.current) clearTimeout(timeOut.current);
timeOut.current = setTimeout(() => updateMyBiddingList(), TIMEOUT);
}
}
console.log('Component is re-rendering... ', aaa);
return ...
上述代码将按以下顺序记录:
有人给我解释更新状态挂钩的工作流程吗?先谢谢你。
这是由于javascript的异步逻辑造成的。我认为您在渲染阶段的某个地方调用了updateMyBiddingList函数,javascript启动了它的进程,并且因为它是异步的,所以react不会等待它完成。这将导致您的应用程序在发出异步请求时冻结。
这是因为React不依赖于那样的异步任务,有两种方法可以模拟您想要的结果。一个我称之为标准版,另一个是不稳定版。
第一种方法是将更新包装在unstable\u batchedUpdate
回调中。顾名思义,此API将在一次对账过程中批量更新,从而减少组件渲染。
所以更新后的代码会是这样的:
import { unstable_batchedUpdates } from "react-dom";
const updateMyBiddingList = async (atDate?: string) => {
try {
console.log('step 0');
const result = await getBiddingCartFromService(atDate ? atDate : myBiddingListState.myBiddingList[0].updatedAt);
// Add unstable API where you cause re-render ⭐
unstable_batchedUpdates(() => {
if (result.responseCode.toString().startsWith('2')) {
setAAA(true);
console.log('step 1');
}
console.log('step 2 ', aaa);
})
}
catch (err) {
if (timeOut.current) clearTimeout(timeOut.current);
timeOut.current = setTimeout(() => updateMyBiddingList(), TIMEOUT);
}
}
这会将日志的顺序更改为
Component is re-rendering... false
step 0
step 1
step 2 false
Component is re-rendering... true
您可以在下面的代码沙盒中看到使用JSON占位符中的假数据运行的代码。
这不是你想做什么就做什么的唯一模式,但对我来说似乎更像:)
此阶段还将更改下一次渲染的函数定义
我坚持使用您的实现,并且不想将use效应
部分拆分为微小的可重用部分,尽管这可能是您需要考虑的事情。
解决方案是将逻辑移动到它所属的位置,这意味着您将在dom树中调用该函数调用的位置。
// instead of aaa and setAAA :)
const [updated, setUpdated] = useState<boolean>(false)
const [hasError, setHasError] = useState<boolean>(false)
const timeOut = useRef<number>()
useEffect(() => {
const updateMyBiddingList = async (atDate?: string) => {
try {
console.log('step 0');
const result = await getBiddingCartFromService(atDate ? atDate : myBiddingListState.myBiddingList[0].updatedAt);
setHasError(false)
if (result.responseCode.toString().startsWith('2')) {
setUpdated(true);
console.log('step 1');
}
console.log('step 2 ', updated);
}
catch (err) {
setHasError(true)
if (timeOut.current) clearTimeout(timeOut.current);
timeOut.current = setTimeout(() => updateMyBiddingList(), TIMEOUT);
}
}
if (!updated || hasError) updateMyBiddingList()
// timeOut.current can also be added here but it is not recommended
}, [updated, hasError])
问题内容: 我有一个外部组件(可观察到的对象),我想听其变化。当对象被更新时,它会发出更改事件,然后我想在检测到任何更改时重新呈现该组件。 对于顶层,这是可能的,但是在组件内不起作用(这是有道理的,因为该方法仅返回一个对象)。 这是一个代码示例: 在内部单击该按钮会调用,但这实际上并不是导致渲染发生的原因(您可以看到它在起作用,因为由创建的文本不会更改)。但是,如果我只是打电话而不是,它就可以正常
我在一个应用程序的前端原型上工作,该应用程序具有给定的JS、React和CoreUI4 React技术栈。我来自Python背景,在网络开发和我给定的技术堆栈方面没有太多经验。当我不得不开始使用钩子时,这一点变得很明显。 问题 我真的不明白为什么它不更新我的和/或不渲染。我需要一个条件渲染,我也使用。 我试图: 从我的主应用程序中传递一个更大的状态,一旦我启动条件逻辑(挂钩规则)就无法工作。 当我
尽管试图避免所有记录在案的陷阱,阻止React在状态更改后重新渲染,但我仍然无法解决我的问题: } 从每个长方体组件调用update函数,并触发长方体网格上新颜色的指定。 试图避免常见的错误: 颜色数组只有在通过扩展运算符从状态复制后才被修改 通过setState()传递新数组 此外,我还处理了两个组件中函数的实例绑定 但是,尽管onClick成功触发了状态更改,但不会进行重新渲染。我在这里缺少的
问题内容: 每次调用时,React都会重新渲染所有组件和子组件吗? 如果是这样,为什么?我以为这个想法是,当状态改变时,React只渲染所需的内容。 在下面的简单示例中,尽管onClick处理程序始终将设置为相同的值,但是在随后的单击中状态不会改变,这两个类在单击文本时都再次呈现。 我曾希望只有在数据更改的情况下才会进行渲染。 这是示例代码,例如JS Fiddle和嵌入式代码段: 问题答案: 每次
我对react还比较陌生,我一直在分解一个web应用程序,并用react组件替换部分。我现在正在开发一个组件,其中包含我创建的几个不同组件。 在新组件中,我在componentDidMount函数中进行API调用,并创建子组件。乍一看,一切看起来都很完美,但当我们在其中一个子组件中进行状态更改,然后在父组件中进行更改时,子组件将其状态重置为更改之前的状态。 我知道发生了什么,州政府没有被传递给家长
我有一个带有对象数组的组件,其中我正在根据字符串进行过滤。问题是当我尝试将此过滤器的返回设置为本地状态时,它会抛出错误,我不太理解原因。 所以,因为我希望这个数组处于我的状态,所以我决定这样做: 插入这一行后发生的事情是这样的: 它开始多次渲染。我假设,每次状态改变时,它都会重新渲染组件(如果我错了,请纠正我)。不过,我不知道它为什么要多次这样做。 因此,我想过使用 useEffect 来实现此处