next.js 为什么当Redux状态发生变化时,useEffect钩子会执行,即使该特定状态没有包含在钩子的依赖数组中?

nsc4cvqm  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(86)
import { shallowEqual, useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import { useRef, useEffect, useState, useCallback, useMemo} from 'react';

const regionsSelector = state => state.regions;
const cellTypeSelector = state => state.cellType;
const subTypeSelector = state => state.subType;
const genesSelector = state => state.genes ? [state.genes] : [];
const backgroundColorSelector = state => state.backgroundColor;
const depthWriteSelector = state => state.depthWrite;
const radiusScaleSelector = state => state.cellRadiusScale;
const geneExpressionLevelScaleSelector = state => state.geneExpressionLevelScale;

const selectedOptionsSelector = createSelector(
  regionsSelector,
  cellTypeSelector,
  subTypeSelector,
  genesSelector,
  backgroundColorSelector,
  depthWriteSelector,
  radiusScaleSelector,
  geneExpressionLevelScaleSelector,
  (selectedRegions, selectedCellTypes, selectedSubTypes, selectedGenes,backgroundColor,depthWrite,radiusScale,geneExpressionLevelScale) => ({
    regions: selectedRegions,
    cellTypes: selectedCellTypes,
    subTypes: selectedSubTypes,
    genes: selectedGenes,
    backgroundColor: backgroundColor,
    depthWrite: depthWrite,
    radiusScale: radiusScale,
    geneExpressionLevelScale: geneExpressionLevelScale,
  }),
);

export default function TestComponent() {
  console.log("Test Componet")

  const selectedOptions = useSelector(selectedOptionsSelector,shallowEqual);

  useEffect (()=> {
    console.log('Selected Options:', selectedOptions.regions,selectedOptions.subTypes,selectedOptions.cellTypes,selectedOptions.genes)

  },[selectedOptions.regions,selectedOptions.subTypes,selectedOptions.cellTypes,selectedOptions.genes])

  useEffect (()=>{
    console.log('Settings: ', )
  },[selectedOptions.backgroundColor,selectedOptions.radiusScale,selectedOptions.depthWrite])

  return <div><h1>testComponent</h1></div>

}

个字符
我有这个react组件来模拟我的应用程序的行为,我遇到的问题是,当只有backgroundColor,radiusScale和depthWrite时,useEffect都运行。另一方面,当[selectedOptions.regions,selectedOptions.subTypes,selectedOptions.cellTypes,selectedOptions.genes]中的仅一个改变时,则仅运行第一个useEffect。有人能解释这种行为并提供解决方案吗?
安装一次后出现问题。

0yycz8jy

0yycz8jy1#

这两种效果的运行主要是因为您选择了太多的状态。你已经创建了8个状态选择器,但随后使用useSelector将它们合并回一个选定对象。

const selectedOptionsSelector = createSelector(
  [
    regionsSelector,
    cellTypeSelector,
    subTypeSelector,
    genesSelector,
    backgroundColorSelector,
    depthWriteSelector,
    radiusScaleSelector,
    geneExpressionLevelScaleSelector
  ],
  (
    selectedRegions,
    selectedCellTypes,
    selectedSubTypes,
    selectedGenes,
    backgroundColor,
    depthWrite,
    radiusScale,
    geneExpressionLevelScale
  ) => ({
    regions: selectedRegions,
    cellTypes: selectedCellTypes,
    subTypes: selectedSubTypes,
    genes: selectedGenes,
    backgroundColor: backgroundColor,
    depthWrite: depthWrite,
    radiusScale: radiusScale,
    geneExpressionLevelScale: geneExpressionLevelScale
  })
);

个字符
即使您使用的是shallowEqual实用函数,它也不能进行足够深的相等性检查。它只检查根级别的属性。
参见shallowEqual

function is(x: unknown, y: unknown) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y
  } else {
    return x !== x && y !== y
  }
}

export default function shallowEqual(objA: any, objB: any) {
  if (is(objA, objB)) return true

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false
  }

  const keysA = Object.keys(objA)
  const keysB = Object.keys(objB)

  if (keysA.length !== keysB.length) return false

  for (let i = 0; i < keysA.length; i++) {
    if (
      !Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
      !is(objA[keysA[i]], objB[keysA[i]])
    ) {
      return false
    }
  }

  return true
}


如果您单独选择每个状态,则在更新不相关的状态时不会触发“其他”效果。
示例如下:

function TestComponent() {
  console.log("Test Component");

  const selectedOptions = useSelector(selectedOptionsSelector, shallowEqual);

  const regions = useSelector(regionsSelector, shallowEqual);
  const subTypes = useSelector(subTypeSelector, shallowEqual);
  const cellTypes = useSelector(subTypeSelector, shallowEqual);
  const genes = useSelector(genesSelector, shallowEqual);
  const backgroundColor = useSelector(backgroundColorSelector);
  const radiusScale = useSelector(radiusScaleSelector);
  const depthWrite = useSelector(depthWriteSelector);

  useEffect(() => {
    console.log(
      "Selected Options 1:",
      selectedOptions.regions,
      selectedOptions.subTypes,
      selectedOptions.cellTypes,
      selectedOptions.genes
    );
  }, [
    selectedOptions.regions,
    selectedOptions.subTypes,
    selectedOptions.cellTypes,
    selectedOptions.genes
  ]);

  useEffect(() => {
    console.log("Selected Options 2:", regions, subTypes, cellTypes, genes);
  }, [regions, subTypes, cellTypes, genes]);

  useEffect(() => {
    console.log(
      "Settings 1: ",
      selectedOptions.backgroundColor,
      selectedOptions.radiusScale,
      selectedOptions.depthWrite
    );
  }, [
    selectedOptions.backgroundColor,
    selectedOptions.radiusScale,
    selectedOptions.depthWrite
  ]);

  useEffect(() => {
    console.log("Settings 2: ", backgroundColor, radiusScale, depthWrite);
  }, [backgroundColor, radiusScale, depthWrite]);

  return (
    <div>
      <h1>testComponent</h1>
    </div>
  );
}


当“深度写入”复选框被切换时,现在当任何“设置2”状态被更新时,“选定选项1”(因为选择器的问题)以及“设置1”和“设置2”效果都被触发。“选定选项2”效果未按预期触发。


的数据

相关问题