【发布时间】:2021-06-13 12:07:36
【问题描述】:
尽管我使用的是 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>
);
}
【问题讨论】:
-
问题不在于
mutating,问题在于一旦您过滤并将data设置为过滤后的值,您就不再拥有data中的其他对象,因此当您删除filter 是没有办法回来的,解决办法是把原始数据单独保存在一块状态,每次需要过滤的时候都使用原始数据。
标签: reactjs search settimeout immutability