Javascript 即使在useEffect中设置之后,状态也返回空数组
我在SO上看到过类似的问题,但无法确定我遇到的问题 我有一个useState变量,在第一次加载时在useEffect中设置。然后,在很晚的时间,触发一个事件,在事件中我检查变量的值,它总是一个空数组[]。但是,我添加了第二个useEffect来跟踪状态变量中的更改,我看不到它在哪里被清空。下面是一些代码来突出我的问题:Javascript 即使在useEffect中设置之后,状态也返回空数组,javascript,reactjs,Javascript,Reactjs,我在SO上看到过类似的问题,但无法确定我遇到的问题 我有一个useState变量,在第一次加载时在useEffect中设置。然后,在很晚的时间,触发一个事件,在事件中我检查变量的值,它总是一个空数组[]。但是,我添加了第二个useEffect来跟踪状态变量中的更改,我看不到它在哪里被清空。下面是一些代码来突出我的问题: import React, { useState, useEffect } from "react"; import { DragAndDrop } from
import React, { useState, useEffect } from "react";
import { DragAndDrop } from "../components";
const AddKidPage = () => {
const [files, setFiles] = useState([]);
useEffect(() => {
var f = [
"nice.pdf",
"verycool.jpg",
"amazing.png",
"goodstuff.mp3",
"thankyou.doc",
];
setFiles(f);
}, []);
useEffect(() => {
console.log(files);
}, [files]);
const handleDrop = (newFiles) => {
let fileList = files;
// HERE FILES = []
for (var i = 0; i < newFiles.length; i++) {
if (!newFiles[i].name) return;
fileList.push(newFiles[i].name);
}
setFiles(fileList);
};
return (
<main>
<DragAndDrop handleDrop={handleDrop}>
<div style={{ height: 300, width: 250 }}>
{files.map((file, i) => (
<div key={i}>{file}</div>
))}
</div>
</DragAndDrop>
</main>
);
};
export default AddKidPage;
import React,{useState,useffect}来自“React”;
从“./components”导入{DragAndDrop};
const AddKidPage=()=>{
const[files,setFiles]=useState([]);
useffect(()=>{
变量f=[
“nice.pdf”,
“verycool.jpg”,
“惊人的.png”,
“好东西,mp3”,
“谢谢你,博士”,
];
设置文件(f);
}, []);
useffect(()=>{
console.log(文件);
},[文件];
常量handleDrop=(新文件)=>{
让fileList=文件;
//此处文件=[]
对于(var i=0;i(
{file}
))}
);
};
导出默认的AddKidPage;
我在跟踪useffect的文件中有1个console.log。以下是组件安装时的输出:
[]
[“nice.pdf”、“verycool.jpg”、“sapping.png”、“goodstuff.mp3”、“thankyou.doc”]
这很有意义——我将数组初始化为空,然后立即用值填充它,然后触发第二个输出。但是,以下是我删除文件后的输出(这会导致执行handleDrop()):
[“newFile.png”]
如您所见,所有其他值都被删除。我在代码“herefiles=[]”中的注释演示了文件useState在何处仍然为空,即使我的输出显示它已填充。useEffect不会第二次输出空数组,所以它在哪里被清空?我检索的值是否错误?非常感谢您对这个谜团的任何帮助。我选择不显示DragAndDrop组件的代码,但它看起来很可靠,并在正确的时间使用正确的值调用handleDrop方法
编辑:
虽然DragAndDrop看起来很可靠,但这可能是我如何调用传入函数的某种问题。。。或者我对{children}的使用。我不确定。下面是DragAndDrop的代码,它完成了这个组件
import React, { useState, useEffect } from "react";
import styled from "styled-components";
const DragAndDrop = ({ handleDrop: externalDrop, children }) => {
const [drag, setDrag] = useState(false);
const [dragCounter, setDragCounter] = useState(0);
const handleDrag = (e) => {
e.preventDefault();
e.stopPropagation();
};
const handleDragIn = (e) => {
e.preventDefault();
e.stopPropagation();
setDragCounter(dragCounter + 1);
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
setDrag(true);
}
};
const handleDragOut = (e) => {
e.preventDefault();
e.stopPropagation();
setDragCounter(dragCounter - 1);
if (dragCounter - 1 === 0) {
setDrag(false);
}
};
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
setDrag(false);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
externalDrop(e.dataTransfer.files);
e.dataTransfer.clearData();
setDragCounter(0);
}
};
useEffect(() => {
var div = document.getElementById("draganddrop-wrapper");
div.addEventListener("dragenter", handleDragIn);
div.addEventListener("dragleave", handleDragOut);
div.addEventListener("dragover", handleDrag);
div.addEventListener("drop", handleDrop);
return () => {
div.removeEventListener("dragenter", handleDragIn);
div.removeEventListener("dragleave", handleDragOut);
div.removeEventListener("dragover", handleDrag);
div.removeEventListener("drop", handleDrop);
};
}, []);
return (
<Wrapper id="draganddrop-wrapper">
{drag && (
<div className="drag-hover">
<div className="drag-overlay">
<div>drop here</div>
</div>
</div>
)}
{children}
</Wrapper>
);
};
const Wrapper = styled.div`
display: inline-block;
position: relative;
.drag-hover {
border: dashed grey 4px;
background: rgba(255, 255, 255, 0.8);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
.drag-overlay {
position: absolute;
top: 50%;
right: 0;
left: 0;
text-align: center;
color: grey;
font-size: 36px;
}
}
`;
export default DragAndDrop;
从“React”导入React,{useState,useffect};
从“样式化组件”导入样式化;
const dragandrop=({handleDrop:externalDrop,children})=>{
const[drag,setDrag]=useState(false);
常量[dragCounter,setDragCounter]=使用状态(0);
常量句柄=(e)=>{
e、 预防默认值();
e、 停止传播();
};
常数handleDragIn=(e)=>{
e、 预防默认值();
e、 停止传播();
设置dragCounter(dragCounter+1);
if(e.dataTransfer.items&&e.dataTransfer.items.length>0){
setDrag(真);
}
};
常量句柄=(e)=>{
e、 预防默认值();
e、 停止传播();
设置dragCounter(dragCounter-1);
如果(拖动计数器-1==0){
setDrag(假);
}
};
常数handleDrop=(e)=>{
e、 预防默认值();
e、 停止传播();
setDrag(假);
如果(e.dataTransfer.files&&e.dataTransfer.files.length>0){
externalDrop(例如dataTransfer.files);
e、 dataTransfer.clearData();
setDragCounter(0);
}
};
useffect(()=>{
var div=document.getElementById(“draganddrop包装器”);
第5部分:附加列表(“dragenter”,handleDragIn);
第二部分:增补列表(“dragleave”,handleDragOut);
第二部分:增补列表(“dragover”,handleDrag);
第二部分添加的列表器(“下降”,手动下降);
return()=>{
第removeEventListener部分(“dragenter”,handleDragIn);
第removeEventListener部分(“dragleave”,handleDragOut);
部门removeEventListener(“dragover”,handleDrag);
第二部分:拆卸通风装置(“下降”,手动下降);
};
}, []);
返回(
{拖动&&(
到这里来
)}
{儿童}
);
};
const Wrapper=styled.div`
显示:内联块;
位置:相对位置;
.拖动鼠标悬停{
边框:灰色虚线4px;
背景:rgba(255,255,255,0.8);
位置:绝对位置;
排名:0;
底部:0;
左:0;
右:0;
z指数:9999;
.拖动覆盖{
位置:绝对位置;
最高:50%;
右:0;
左:0;
文本对齐:居中;
颜色:灰色;
字体大小:36px;
}
}
`;
导出默认DragAndDrop;
这是因为您正在变异文件
变量,而不是克隆它
改变
let fileList = files;
到
更新
const handleDrop = useCallback((newFile) => {
if (newFile.type === "image/png") {
setFile(newFile.name);
}
}, []);
谢谢你的建议。我试过了,结果是一样的。我添加了以下代码:constfilelist=[…files];console.log(文件列表);我得到的输出是[]。尝试更改
constfilelist=[…文件]
tolet fileList=[…文件]代码>不幸的是,let的行为是相同的。我已经修改了我的问题以包含其他组件。我不确定这是否应该归咎于它,但我想我会加上它。@BrianLegg您是说组件装载后第一次调用handledrop
,文件
数组是控制台。在//此处…
注释中将记录为空?dragandrop
组件将不相关,因为它不会直接与文件
数组交互。你能在codesandbox上提供你的代码样本吗?
const handleDrop = useCallback((newFile) => {
if (newFile.type === "image/png") {
setFile(newFile.name);
}
}, []);