经验:我是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);
};
您可以找到有问题的文件和代码HERE(向下滚动至change
函数)
从“按地区列出的Fitler”中选择一个地区
在控制台中查看错误/输出
答案 0 :(得分:1)
您正在将状态更新为对象数组,最后一项将是过滤后的列表
相反,传入包含已过滤国家/地区的单个数组。
请注意,由于您正在修改整个国家/地区,因此您第二次选择其他地区时,您的州将丢失。
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);
}