为了账号安全,请及时绑定邮箱和手机立即绑定

反应中的 useState() 不会更新数据 - 这是 sort() 问题吗?

反应中的 useState() 不会更新数据 - 这是 sort() 问题吗?

holdtom 2022-05-26 14:03:34
当我在网站加载后单击按钮对有关国家/地区的数据进行排序时,数据显示正确。但是当我想按不同的值再次对其进行排序时,数据不会更新,状态也不会更新,但是,该功能运行良好,因为我可以看到控制台中的结果已正确排序。这种奇怪行为的原因是什么?感谢您的时间。 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;
查看完整描述

3 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

Array.sort()方法不返回新引用,它返回相同的引用。所以我假设在sortedCountriesstate 中存储了相同的 props.countries 引用,这就是为什么第二个按钮单击不设置状态(它是相同的引用),我可以给你简单的解决方案,只是在这种情况下setSortedCountries(sortedResults)用这个更改这一行setSortedCountries([...sortedResults])复制的 sortedResults 将被传递给setSortedCountries(新参考)。



查看完整回答
反对 回复 2022-05-26
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

让 sortedResults = countries.sort

此行正在对国家道具进行排序并将 sortedResults 设置为该指针

让我们假设指针保存在 mem |0001| 为简单起见

第一次单击后,该函数被触发,道具被排序,并通过 setSortedCountries(设置状态)设置 sortedResults。

这会触发您想要的渲染,因为之前的状态是未定义的,现在状态指向 |0001|

当您的函数再次运行时,排序函数将触发,并在 |0001| 上工作 并返回——你猜对了——|0001| 但是使用新的排序数组。

当你第二次去设置状态时,实际上并没有改变任何状态,因为之前的国家是 |0001| 而你想改成的国家是|0001|

那么我们能做些什么对我的好先生呢?

首先,我需要您考虑一下这个问题,想想如何解决这个问题并尝试应用一些更改。

您可以尝试做的是将国家道具复制到具有相同值的新数组指针,然后对其进行排序,然后将 sortedCountries 状态设置为该列表。

那有意义吗?

顺便说一句,这也是出于类似的原因,如果您尝试直接在新对象状态上设置状态,新对象状态将完全等于您设置的状态。这里没有任何真正的魔法。React 不会自动合并你以前的对象状态和新的对象状态,除非你明确告诉它这样做。

从某种意义上说,您已经告诉 react 检查两个州之间的差异,一个旧国家和一个新国家(在 Vdom 的幕后),但是对于反应,这两个国家没有区别。并且由于两个对象状态没有区别,因此不会有实际的 DOM 更改。

因此,您将指针设置两次不会产生实际变化。

因此,您必须将 state 设置为具有新值的实际新指针,以便 react 虚拟 dom 可以比较两个状态(以前的国家列表)和新的国家列表。

希望有帮助


查看完整回答
反对 回复 2022-05-26
?
开心每一天1111

TA贡献1836条经验 获得超13个赞

这在 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;


查看完整回答
反对 回复 2022-05-26
  • 3 回答
  • 0 关注
  • 314 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信