Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useDeepCompareEffect 存在依赖变更但是不触发的场景 #2663

Open
cydiacen opened this issue Oct 28, 2024 · 2 comments
Open

useDeepCompareEffect 存在依赖变更但是不触发的场景 #2663

cydiacen opened this issue Oct 28, 2024 · 2 comments

Comments

@cydiacen
Copy link

复现组件:

function Components() {
      const [value, setValue] = useState([
        {
          label: '1'
        }
      ]);
      useDeepCompareEffect(() => {
        console.log('触发');
      }, [value]);

      const handleSearch = (valueStr: string) => {
        const newValue = [...value];
        // newValue[0].label = valueStr;  // 这么写不会触发  useDeepCompareEffect
        newValue[0] = { label: valueStr }; // 这么写可以 触发  useDeepCompareEffect
        setValue(newValue);
      };

      const handleClick = () => {
        console.log('点击', value);
      };

      return (
        <div id='box'>
          {value.map((item, index) => {
            return (
              <div key={index}>
                <Input
                  value={item.label}
                  onChange={(e) => {
                    handleSearch(e.target.value);
                  }}
                />
                <Button onClick={handleClick}>获取</Button>
              </div>
            );
          })}
        </div>
      );
    }

本质上是因为ref缓存了之前的对象,如果是通过直接修改对象的值进行的变更,那么在比较的时候,也是拿的最新的已经产生变更的ref进行比较。这样子并不会触发useDeepCompareEffect 的回调,可以考虑改成clone快照 使其与外部环境解耦。

@ruixingshi
Copy link
Contributor

我觉得这个问题的本质是setState时,newValue[0].label = valueStr,仅对value进行了浅拷贝,label的引用地址是没变的。
useDeepCompareEffect 使用的react-fast-compare 是递归比较,先比较引用,再进行值对比。因此label的比较结果认为是相同的。

如虑改成clone,useDeepCompareEffect的性能会变得很差,甚至即使dependence没变时,也会出现大量无效对比。

@caorushizi
Copy link
Contributor

建议使用immerjs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants