经验:我是 React 的初学者。
我正在尝试学习的:钩子(useState
( - 但我不知道如何更新状态并用它重新渲染视图。据我了解,如果更新的状态与上一个有点相似,React 不会重新渲染视图......谷歌搜索后,我试图复制状态并以某种方式更新它,但我错过了一些东西,我不知道是什么。
我在项目中尝试做什么:当用户从下拉列表中选择区域时,我有一个想要过滤的国家/地区列表。这是在选择发生时触发的函数,以及我希望解释我正在尝试做什么的评论:
const change = event => {
//copy the `data` state (which has a list of all the countries)
let newData = [...data];
console.log(newData);
//filter through the countries list to get only those with the selected region
let filtered = newData.filter(obj => obj.region === event.target.value);
console.log(filtered);
//change the countries list with the filtered one, and rerender the view
setData([data, newData]);
console.log(data);
};
您可以在此处找到有问题的文件和代码(向下滚动以转到change
函数(
从"按地区划分的 Fitler 下拉菜单"中选择一个区域
在控制台中查看错误/输出
您正在将状态更新为对象数组,最后一项将是筛选的列表
相反,传入包含筛选国家/地区的单个数组。
请注意,第二次选择其他区域时,您的州将丢失,因为您正在修改整个国家/地区集合。
setData(data.filter(obj => obj.region === event.target.value))
那么,我们可以做些什么来避免失去国家呢?
我们可以根据所选区域过滤列表。
在我更改代码的地方添加了注释
export default function CountriesList() {
const [data, setData] = useState([]);
const [distinctRegions, setDistinctRegions] = useState([]);
const [loading, setLoading] = useState(true);
// added state to track the selected region
const [selectedRegion, setSelectedRegion] = useState("");
useEffect(() => {
CountriesAPI().then(res => {
onLoad(res);
setLoading(false);
});
}, []);
const onLoad = dataList => {
setData(...data, dataList);
getRegions(dataList);
};
const getRegions = dataList => {
let regions = [];
dataList.map(dataItem =>
dataItem.region.length ? regions.push(dataItem.region) : ""
);
let regionsFiltered = regions.filter(
(item, index, arr) => arr.indexOf(item) === index
);
setDistinctRegions(...distinctRegions, regionsFiltered);
};
const renderLoading = () => {
return <div>Loading...</div>;
};
// now we only need to update the selected region
const change = event => {
setSelectedRegion(event.target.value);
};
const renderData = (dataList, distinctRegionsItem) => {
if (dataList && dataList.length) {
return (
<div>
<Container>
<Input type="text" placeholder="Search for a country..." />
<Select className="select-region" onChange={change}>
<option value="" hidden>
Filter by region
</option>
// added show all
<option value="">Show All</option>
{distinctRegionsItem.map(item => {
return (
<option key={item} value={item}>
{item}
</option>
);
})}
</Select>
</Container>
<CardList>
// filter the array based on selectedRegion and then render the list.
// if selectedRegion is empty show all
{dataList
.filter(
country => !selectedRegion || country.region === selectedRegion
)
.map(country => (
<CountryCard
population={country.population}
region={country.region}
capital={country.capital}
flag={country.flag}
key={country.alpha3Code}
id={country.alpha3Code}
name={country.name}
/>
))}
</CardList>
</div>
);
} else {
return <div>No items found</div>;
}
};
return loading ? renderLoading() : renderData(data, distinctRegions);
}