reactjs - 尽管我使用的是 prevState,但 SetTimeout 会改变我的状态
问题描述
尽管我使用的是 prevState,但 SetTimeout 会改变我的状态。第一个搜索功能起作用并过滤掉数组。setData 完全过滤和更改数据数组。如果您输入内容、搜索并删除输入,您将看不到返回的数据。
export default function App() {
const [data, setData] = useState([]);
const [inputValue, setInputValue] = useState("");
const [isLoading, setIsLoading] = useState();
// sets inputValue state for each keystroke
const inputValueChangeHandler = (event) => {
setInputValue(event.target.value);
};
useEffect(() => {
setIsLoading(true);
// creates timer for filtering data
const timer = setTimeout(() => {
setData((prevState) => {
// sets filter object after one second in order to filter results
const filteredData = prevState
// filters data according to filter value
.filter((item, index) => {
// return array of object values and drill down the array
const flattenedItem = Object.values(item).map((itemLevel2) => {
// if typeof the itemLevel2 is object (address, company), convert it to array else return the string
if (typeof itemLevel2 === "object") {
return Object.values(itemLevel2).map((itemLevel3) => {
// if typeof the itemLevel3 is object (geo), convert it to an array else return the string
if (typeof itemLevel3 === "object") {
return Object.values(itemLevel3);
} else {
return itemLevel3;
}
});
} else {
return itemLevel2;
}
});
return flattenedItem
.flat(2) // creates a new array with all sub-array elements concatenated into it recursively up to the specified depth (2).
.join(" ") // converts array to string
.toLowerCase()
.includes(inputValue.toLowerCase()); // searches if string includes filterValue
});
return filteredData;
});
setIsLoading(false);
}, 1000);
// clear timer while unmounting
return () => clearTimeout(timer);
}, [inputValue]);
return (
<StyledApp>
{data.map((item) => (
<Card key={item.id}>
<pre>{JSON.stringify(item, null, 2)}</pre>
</Card>
))}
</StyledApp>
);
}
解决方案
添加另一个状态并在其中存储数据并过滤它解决了这个问题。
export default function App() {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [inputValue, setInputValue] = useState("");
const [isLoading, setIsLoading] = useState();
// sets inputValue state for each keystroke
const inputValueChangeHandler = (event) => {
setInputValue(event.target.value);
};
useEffect(() => {
setIsLoading(true);
// creates timer for filtering data
const timer = setTimeout(() => {
setFilteredData((prevState) => {
// sets filter object after one second in order to filter results
const filteredData = [...data]
// filters data according to filter value
.filter((item, index) => {
// return array of object values and drill down the array
const flattenedItem = Object.values(item).map((itemLevel2) => {
// if typeof the itemLevel2 is object (address, company), convert it to array else return the string
if (typeof itemLevel2 === "object") {
return Object.values(itemLevel2).map((itemLevel3) => {
// if typeof the itemLevel3 is object (geo), convert it to an array else return the string
if (typeof itemLevel3 === "object") {
return Object.values(itemLevel3);
} else {
return itemLevel3;
}
});
} else {
return itemLevel2;
}
});
return flattenedItem
.flat(2) // creates a new array with all sub-array elements concatenated into it recursively up to the specified depth (2).
.join(" ") // converts array to string
.toLowerCase()
.includes(inputValue.toLowerCase()); // searches if string includes filterValue
});
return filteredData;
});
setIsLoading(false);
}, 1000);
// clear timer while unmounting
return () => clearTimeout(timer);
}, [inputValue, data]);
return (
<>
{filteredData.map((item) => (
<Card key={item.id}>
<pre>{JSON.stringify(item, null, 2)}</pre>
</Card>
))}
</>
);
}
推荐阅读
- python - 从文本文件中读取(有点)非结构化数据以创建 Python 字典
- r - 如何将 -k 或 --insecure 参数传递给 R 包“httr”中的 curl?
- amazon-iam - 启动管道时出现 AccessDeniedException
- python - 在 django 中设置守护进程的最佳方法是什么
- shell - 如何读取过去一小时的日志文件
- amazon-web-services - AWS RDS 快照包括什么?
- javascript - 如何在 JavaScript(或 TypeScript 或 Dart)中访问“浏览器”对象
- wordpress - Wordpress - 尝试以两种不同的方式从自定义表单中显示日期
- f# - 使用模式匹配将泛型类型映射到记录
- batch-file - 如何在批处理文件中使用波兰语字符?