Javascript 如何使用useState在react功能组件的循环中正确设置状态
假设我正在上传一堆文件,并试图跟踪正在进行的文件,这样每当上传完成时,我都会减少我的状态,直到所有文件都完成,最后我将上传状态更改为Javascript 如何使用useState在react功能组件的循环中正确设置状态,javascript,reactjs,closures,react-hooks,Javascript,Reactjs,Closures,React Hooks,假设我正在上传一堆文件,并试图跟踪正在进行的文件,这样每当上传完成时,我都会减少我的状态,直到所有文件都完成,最后我将上传状态更改为false: (这里我做了一个sleep函数来模拟上传过程) import React,{useState}来自“React”; 常量睡眠=(ms,dev=1)=>{ 常量msWithDev=(Math.random()*dev+1)*ms 返回新承诺(resolve=>setTimeout(resolve,msWithDev)) } 函数计数器(){ 常量[,se
false
:
(这里我做了一个sleep
函数来模拟上传过程)
import React,{useState}来自“React”;
常量睡眠=(ms,dev=1)=>{
常量msWithDev=(Math.random()*dev+1)*ms
返回新承诺(resolve=>setTimeout(resolve,msWithDev))
}
函数计数器(){
常量[,setSortEnabled]=使用状态(true)
const[count,setCount]=useState(0)
常数arr=[1,2,3,4,5]
const upload=async()=>{
等待睡眠(1000)
设置计数(c=>c-1)
log(`count state:${count}`)
如果(计数==0){
console.warn('再次将排序设置为启用')
setSortEnabled(真)
}
}
const onClick=()=>{
console.warn('排序设置为禁用')
arr.forEach(项目=>{
设置计数(c=>c+1)
控制台错误(计数)
上传()
})
}
返回(
点击我!
);
}
导出默认计数器;
问题在于上传
function `console.log(\`count state: ${count}\`)`
始终记录0
,这意味着状态从未更新过
我做错了什么
这意味着状态从未更新过
它确实得到更新,您只是记录了过时的值
闭包是捆绑在一起(封闭)的函数与其周围状态(词汇环境)的引用的组合。换句话说,闭包允许您从内部函数访问外部函数的作用域
要修复它,请使用setState
:
这意味着状态从未更新过
它确实得到更新,您只是记录了过时的值
闭包是捆绑在一起(封闭)的函数与其周围状态(词汇环境)的引用的组合。换句话说,闭包允许您从内部函数访问外部函数的作用域
要修复它,请使用setState
:
您必须使用
Promise.all
等待上传所有文件,而不是依赖计数。在您的情况下,count是从closure接收的,因此即使状态被更新,count变量也不会受到影响
您可以使用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;
函数计数器(){
常量[,setSortEnabled]=使用状态(true)
常数arr=[1,2,3,4,5]
const upload=async()=>{
等待睡眠(1000);
}
const onClick=async()=>{
console.warn('排序设置为禁用')
const promises=arr.map(项=>{
控制台错误(计数)
返回上载()
});
等待承诺。所有(承诺);
console.warn('再次将排序设置为启用')
setSortEnabled(真)
}
返回(
点击我!
);
}
导出默认计数器;
更新:
要绕过计数状态的闭包问题,可以使用refs和useffect。但是,这是一种变通方法,不应被优先考虑
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;
import React,{useState}来自“React”;
常量睡眠=(ms,dev=1)=>{
常量msWithDev=(Math.random()*dev+1)*ms
返回新承诺(resolve=>setTimeout(resolve,msWithDev))
}
函数计数器(){
常量[,setSortEnabled]=使用状态(true)
const[count,setCount]=useState(0)
常数arr=[1,2,3,4,5]
const countRef=useRef(计数);
useffect(()=>{
countRef.current=计数;
},[计数];
const upload=async()=>{
等待睡眠(1000)
设置计数(c=>c-1)
log(`count state:${count}`)
如果(countRef.current==0){
console.warn('再次将排序设置为启用')
setSortEnabled(真)
}
}
const onClick=()=>{
console.warn('排序设置为禁用')
arr.forEach(项目=>{
设置计数(c=>c+1)
上传();
})
}
返回(
点击我!
);
}
导出默认计数器;
您必须使用Promise.all
等待上传所有文件,而不是依赖计数。在您的情况下,count是从closure接收的,因此即使状态被更新,count变量也不会受到影响
您可以使用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;
函数计数器(){
常量[,setSortEnabled]=使用状态(true)
常数arr=[1,2,3,4,5]
const upload=async()=>{
等待睡眠(1000);
}
const onClick=async()=>{
console.warn('排序设置为禁用')
const promises=arr.map(项=>{
控制台错误(计数)
返回上载()
});
等待承诺。所有(承诺);
console.warn('再次将排序设置为启用')
setSortEnabled(真)
}
返回(
点击我!
);
}
导出默认计数器;
更新:
要绕过计数状态的闭包问题,可以使用refs和useffect。但是,这是一种变通方法,不应被优先考虑
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;
import React,{useState}来自“React”;
常量睡眠=(ms,dev=1)=>{
常量msWithDev=(Math.random()*dev+1)*ms
返回新承诺(resolve=>setTimeout(resolve,msWithDev))
}
函数计数器(){
常量[,setSortEnabled]=使用状态(true)
const[count,setCount]=useState(0)
常数arr=[1,2,3,4,5]
const countRef=useRef(计数);
useffect(()=>{
countRef.current=计数;
},[计数];
const upload=async()=>{
等待睡眠(1000)
设置计数(c=>c-1)
log(`count state:${count}`)
如果(countRef.current==0){
console.warn('再次将排序设置为启用')
setSortEnabled(真)
}
}
const onClick=()=>{
console.warn('排序设置为禁用')
arr.forEach(项目=>{
设置计数(c=>c+1)
上传();