【问题标题】:React useEffect not rerendering反应useEffect不重新渲染
【发布时间】:2020-06-25 05:03:15
【问题描述】:

我正在尝试更改数组中的值并使用 useEffect 重新渲染组件,但 useEffect 未触发。值正在更改,但调用 useState 无效。

const handleOptionClick = (e) => {

            var el = document.getElementById(e.currentTarget.id);
            var tar = el.getAttribute("data");
            
            var ans = awnsers;
            ans.map((res) => {
                if (res.Awnser === tar) {
                  res.IsChecked = !res.IsChecked;
                  return true;
                }
                return true;
              });
              setAwnsers(ans);
     }

和

useEffect(() => {
        console.log(awnsers);
    },[awnsers])

【问题讨论】:

标签: reactjs react-hooks use-effect


【解决方案1】:

由于您在ans 上执行map,因此我认为它是一个数组。数组是通过引用复制的。因此,为了响应重新渲染awnsers,您必须创建一个新数组。

var ans = [...awnsers]; // or JSON.parse(JSON.stringify(awnsers)) for deep clone
            ans.map((res) => {
                if (res.Awnser === tar) {
                  res.IsChecked = !res.IsChecked;
                  return true;
                }
                return true;
              });
              setAwnsers(ans);

Awnsers 也是错字吗?你是说Answers吗?

【讨论】:

    【解决方案2】:

    你不会保存你保存在状态中的 array::map 函数的结果,所以基本上awnsers 数组中的状态引用值不会改变,组件也不会重新渲染。

    const handleOptionClick = (e) => {
      var el = document.getElementById(e.currentTarget.id);
      var tar = el.getAttribute("data");
            
      setAwnsers(prevAwnser => prevAwnser.map(res => ({
        ...res,
        IsChecked: res.Awnser === tar ? !res.IsChecked : res.IsChecked,
      })));
    }
    

    【讨论】:

      【解决方案3】:

      React 在更新状态时执行 Object.is 比较,如果先前和当前状态的引用相同,则检查失败并且不会触发重新渲染

      同样 map 返回数组的新引用,你不能改变原始数组,而是以不可变的方式更新它

      const handleOptionClick = (e) => {
      
              var el = document.getElementById(e.currentTarget.id);
              var tar = el.getAttribute("data");
              
              var ans = awnsers; // Check for typo
              ans = ans.map((res) => {
                  if (res.Awnser === tar) {
                    {...res, IsChecked:!res.IsChecked};
                  }
                  return res;
                });
                setAwnsers(ans);
       }
      

      附:您还可以使用功能 setState 方法来更新状态,因为您正在根据以前的值更新当前状态

        const handleOptionClick = (e) => {
      
              var el = document.getElementById(e.currentTarget.id);
              var tar = el.getAttribute("data");
              setAwnsers(prevAns => ans.map((res) => {
                  if (res.Awnser === tar) {
                    {...res, IsChecked:!res.IsChecked};
                  }
                  return res;
              }));
       }
      

      【讨论】:

        猜你喜欢
        • 2022-08-19
        • 1970-01-01
        • 2022-01-04
        • 2019-12-13
        • 2020-03-08
        • 2019-10-07
        • 2020-07-06
        • 1970-01-01
        • 2020-04-23
        相关资源
        最近更新 更多