加载网站后,当我单击按钮对有关国家/地区的数据进行排序时,数据显示正确。但是,当我想按不同的值再次排序时,数据不会更新,状态也不会更新,然而,该函数运行良好,因为我可以看到控制台中的结果排序正确。这种奇怪行为的原因是什么?谢谢你抽出时间。
function AllCountries({ countries }) {
const [sortedCountries, setSortedCountries] = useState([]);
useEffect(() => {
console.log(sortedCountries)
}, [sortedCountries])
const sortResults = (val) => {
let sortedResults = countries.sort((a, b) => {
if (val === "deaths") {
return b.TotalDeaths - a.TotalDeaths;
} else if (val === "cases") {
return b.TotalConfirmed - a.TotalConfirmed;
} else if (val === "recovered") {
return b.TotalRecovered - a.TotalRecovered;
}
});
console.log(sortedResults);
setSortedCountries(sortedResults);
};
return (
<div className="all-container">
<p>Sort countries by the highest number of:</p>
<button onClick={() => sortResults("deaths")}>Deaths</button>
<button onClick={() => sortResults("cases")}>Cases</button>
<button onClick={() => sortResults("recovered")}>Recoveries</button>
<ul className="all-countries">
{sortedCountries.map((country, key) => {
return <li key={key}>{country.Country}</li>;
})}
</ul>
</div>
);
}
export default AllCountries;
Array.sort()
方法不返回新的引用,而是返回相同的引用。因此,我假设在sortedCountries
状态下存储了相同的props.countries引用,这就是为什么第二次单击按钮不会设置状态(它是相同的引用(,我可以给你一个简单的解决方案,只需用setSortedCountries([...sortedResults])
更改这行setSortedCountries(sortedResults)
,在这种情况下,sortedResults的副本将传递给setSortedCountries
(新引用(。
let sortedResults=countries.sort
此行对countries道具进行排序,并将sortedResults设置为该指针
为了简化,我们假设指针保持在mem|0001|
第一次单击后,函数被激发,道具被排序,sortedResults通过setSortedCountries设置(设置状态(。
这会触发您想要的渲染,因为以前的状态是未定义的,现在该状态指向|0001|
当您的函数再次运行时,排序函数会启动,在|0001|上执行它的工作,并返回——您猜对了——|0001|,但返回的是新排序的数组。
当您第二次设置状态时,实际上没有任何状态更改,因为上一个国家/地区是|0001|,而您要更改的国家/地区为|0001|
那么我们能做些什么呢,先生?
首先,我需要你思考一下这个问题,思考如何解决这个问题,并尝试应用一些更改。
您可以尝试将countries道具复制到具有相同值的新数组指针,然后对其进行排序,然后将sortedCountrys状态设置为该列表。
这有道理吗?
顺便说一句,这也是出于类似的原因,如果您尝试直接在新对象状态上设置state,则新对象状态将与您设置的状态完全相同。这里没有任何真正的魔法。React不会自动合并您以前的对象状态和新的对象状态,除非您明确告诉它这样做
从某种意义上说,你已经告诉做出反应,检查两个州之间的差异,一个旧国家和一个新国家(在Vdom的幕后(,但要做出反应,这两个州没有区别。由于这两种对象状态没有差异,因此不会有实际的DOM更改。
因此,两次设置指针不会产生实际的更改。
因此,您必须将state设置为具有新值的实际新指针,以便react虚拟dom可以比较这两个状态(以前的国家列表(和新的国家列表。
希望能帮助
-
React中有一个小问题,另一个解决方案是使用useReducer。例如:
function reducer(state, action) {
return [...state, ...action];
}
function AllCountries({ countries }) {
const [sortedCountries, setSortedCountries] = useReducer(reducer, []);
useEffect(() => {
console.log(sortedCountries)
}, [sortedCountries])
const sortResults = (e, val) => {
e.preventDefault();
let sortedResults = countries.sort((a, b) => {
if (val === "deaths") {
return b.TotalDeaths - a.TotalDeaths;
} else if (val === "cases") {
return b.TotalConfirmed - a.TotalConfirmed;
} else if (val === "recovered") {
return b.TotalRecovered - a.TotalRecovered;
}
});
console.log(sortedResults);
setSortedCountries(sortedResults);
};
return (
<div className="all-container">
<p>Sort countries by the highest number of:</p>
<button onClick={(e) => sortResults(e, "deaths")}>Deaths</button>
<button onClick={(e) => sortResults(e, "cases")}>Cases</button>
<button onClick={(e) => sortResults(e, "recovered")}>Recoveries</button>
<ul className="all-countries">
{sortedCountries.map((country, key) => {
return <li key={key}>{country.Country}</li>;
})}
</ul>
</div>
);
}
export default AllCountries;