考虑一下,我正在上传一堆文件,并且试图跟踪正在进行的文件,因此,每当上传完成时,我都会减小状态,直到所有操作都完成,最后将上传状态更改为{ {1}}:
(在这里,我做了一个false
函数来模仿上传过程)。
sleep
问题出在import React, { useState} from "react";
const sleep = (ms, dev =1 ) => {
const msWithDev = (Math.random() * dev + 1) * ms
return new Promise(resolve => setTimeout(resolve, msWithDev))
}
function Counter() {
const [, setSortEnabled] = useState(true)
const [count, setCount] = useState(0)
const arr = [1, 2, 3, 4, 5]
const upload = async () => {
await sleep(1000)
setCount(c => c - 1)
console.log(`count state: ${count}`)
if (count === 0) {
console.warn('Sort set to enabled again.')
setSortEnabled(true)
}
}
const onClick = () => {
console.warn('Sort set to disabled.')
arr.forEach(item => {
setCount(c => c + 1)
console.error(count)
upload()
})
}
return (
<>
<button onClick={onClick}>Click me!</button>
</>
);
}
export default Counter;
,
upload
始终记录function `console.log(\`count state: ${count}\`)`
,这意味着状态从未更新过。
我在做什么错了?
答案 0 :(得分:1)
这意味着状态从未更新
它确实已更新,您只是在记录陈旧的值 because of closures。
闭包是捆绑在一起(封闭)的函数和对其周围状态(词汇环境)的引用的组合。换句话说,闭包使您可以从内部函数访问外部函数的作用域。
要解决此问题,请使用FROM ubuntu:18.04
functional updates:
setState
答案 1 :(得分:1)
您必须使用Promise.all
来等待所有文件上传,而不是依靠计数。在您的情况下,计数是从关闭接收的,因此即使状态已更新,计数变量也不受影响。
您可以使用Promise.all like
实现上述逻辑function Counter() {
const [, setSortEnabled] = useState(true)
const arr = [1, 2, 3, 4, 5]
const upload = async () => {
await sleep(1000);
}
const onClick = async () => {
console.warn('Sort set to disabled.')
const promises = arr.map(item => {
console.error(count)
return upload()
});
await Promise.all(promises);
console.warn('Sort set to enabled again.')
setSortEnabled(true)
}
return (
<>
<button onClick={onClick}>Click me!</button>
</>
);
}
export default Counter;
更新:
要解决count状态的关闭问题,可以使用refs和useEffect。但是,这是一种解决方法,因此不应该被优先使用
import React, { useState} from "react";
const sleep = (ms, dev =1 ) => {
const msWithDev = (Math.random() * dev + 1) * ms
return new Promise(resolve => setTimeout(resolve, msWithDev))
}
function Counter() {
const [, setSortEnabled] = useState(true)
const [count, setCount] = useState(0)
const arr = [1, 2, 3, 4, 5]
const countRef = useRef(count);
useEffect(() => {
countRef.current = count;
}, [count ]);
const upload = async () => {
await sleep(1000)
setCount(c => c - 1)
console.log(`count state: ${count}`)
if (countRef.current === 0) {
console.warn('Sort set to enabled again.')
setSortEnabled(true)
}
}
const onClick = () => {
console.warn('Sort set to disabled.')
arr.forEach(item => {
setCount(c => c + 1)
upload();
})
}
return (
<>
<button onClick={onClick}>Click me!</button>
</>
);
}
export default Counter;