【问题标题】:How can I deep compare objects/arrays in useEffect/React?如何深入比较 useEffect/React 中的对象/数组?
【发布时间】:2022-01-09 16:54:36
【问题描述】:

我只是想知道,如何深入比较 useEffect 或 React Hooks 中的对象/数组?我正在尝试使其也以与钩子版本相同的方式工作。

在以前的版本中,我的做法如下;

componentWillReceiveProps(nextProps){
   const { settings: { config = {} } = {}, pluginData = [] } = this.props
   const { settings: { config: nextConfig = {} } = {}, pluginData: nextPluginData = [] } = nextProps

   if(!_.isEqual(config, nextConfig) && !_.isEqual(pluginData, nextPluginData )){
        //do sth with new props
   }
}

下一个版本;

useEffect(() => {
 // do sth with new props
}, [props.settings.config, props.pluginData])

如您所见,我使用 lodash 的 isEqual 来比较它是否是同一个对象/数组。如何在钩子中做到这一点?当我将嵌套对象/数组传递给 useEffect 的依赖数组时,React 如何比较?是深比较还是浅比较?

还有;

如果我不确定 props 有设置和配置怎么办 在以前的版本中,我的做法如下;

const { settings = {} } = nextProps

在钩子版本中怎么做?是否应该继续使用相同的方法?

PS:config 是嵌套对象,pluginData 是对象数组。

//// 要求澄清后

UNSAFE_componentWillReceiveProps(nextProps) {
    const {
      settings: { config: { data: { enabled: nextEnabled = false } = {} } = {} } = {},
      pluginData: nextPluginData = []
    } = nextProps || {}

    if (nextEnabled) {
      if (nextPluginData[0]) {
        this.setState({ disabled: !nextPluginData[0][nextEnabled] })
      }
    }
  }

我正在重写已经用类 cmp 编写的组件之一。如何将这段代码从类 cmp 转换为 hook cmp?

【问题讨论】:

  • 由于它们在父组件中更改时是props,因此它们应该有一个新的引用,并且您的子组件将被重新渲染。没有必要深入比较它们。但是,如果您在这个问题背后的原因是限制重新渲染的数量(没有明确说明),您应该查看memo
  • 我真的知道,每次父渲染时它们都会获得一个新的引用,但是如果您使用 lodash 的 isEqual 并且您的对象内部没有函数(渲染期间创建的 fn)更改了引用没关系。它将按预期进行比较,并在实际情况下为真。我的观点是,如果 props 真的发生变化,则从 props 中获取新值。
  • 也许您对用例的解释不够清楚。维维尔是正确的。您不需要或不应该进行深度相等,因为您可以像所做的那样使用深度依赖,并且当 that 值与之前的渲染相比发生变化时,触发效果打回来。 “平等”问题是否与数组有关?

标签: arrays reactjs object react-hooks


【解决方案1】:

根据您的评论,您可以执行以下操作:

const [config, setConfig] = useState(undefined);
const [pluginData, setPluginData] = useState(undefined);

useEffect(() => {
    if(!_.isEqual(config, props.settings.config) && !_.isEqual(pluginData, props.pluginData)) {
        //do sth with new props

        // Update old props to have them actual for the next comparison
        setConfig(props.settings.config);
        setPluginData(props.pluginData);
    }
}, [props.settings.config, props.pluginData])

基本上,您可以先了解旧道具的状态,然后对其进行深度比较。

【讨论】:

  • 很好的答案。在您的示例中,有两个比较,一个是明显的 isEqual 您所做的,第二个是在依赖项[props.settings.config, props.pluginData] 这两个比较之间有什么区别?不一样吗?我的意思是,当我们将 useEffect 与依赖数组一起使用时,React 不会深入比较 configpluginData 吗?
猜你喜欢
  • 2012-10-20
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2015-07-07
  • 2016-09-01
  • 2023-01-13
  • 1970-01-01
相关资源
最近更新 更多