首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

即使对象相同,React- Lodash isEqual也会返回false

_.isEqual 是 Lodash 库中的一个方法,用于深度比较两个值是否相等。在 React 中,即使对象看起来相同,_.isEqual 返回 false 的情况通常是因为这两个对象在内存中的引用不同,即它们是两个不同的实例。

基础概念

  • 引用相等性:在 JavaScript 中,如果两个变量指向同一个对象实例,那么它们是引用相等的。
  • 结构相等性:即使两个对象的内容完全相同,但如果它们位于内存中的不同位置,那么它们是结构相等的,但不是引用相等的。

为什么会出现这种情况?

当你在 React 组件中使用 _.isEqual 来比较两个对象时,即使这两个对象的内容看起来完全一样,如果它们是通过不同的 new 表达式或者不同的函数调用创建的,那么它们在内存中的地址是不同的,因此 _.isEqual 会返回 false

如何解决?

  1. 使用不可变数据结构:使用像 Immutable.js 这样的库来创建不可变的数据结构,这样每次更新都会返回一个新的对象实例,而不会改变原始对象。
代码语言:txt
复制
import { Map } from 'immutable';

const obj1 = Map({ a: 1, b: 2 });
const obj2 = obj1.set('b', 3);

console.log(_.isEqual(obj1, obj2)); // false
  1. 浅比较:如果你确定对象的结构不会很深,可以使用浅比较。但是这种方法对于嵌套对象不适用。
代码语言:txt
复制
const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };

console.log(_.isEqual(obj1, obj2)); // true
  1. 记忆化(Memoization):使用 React 的 useMemo 或者 useCallback 钩子来记忆化组件或者函数,这样只有在依赖项发生变化时才会重新计算。
代码语言:txt
复制
import React, { useMemo } from 'react';
import _ from 'lodash';

function MyComponent({ data }) {
  const memoizedData = useMemo(() => data, [data]);

  // 使用 memoizedData 进行渲染或其他操作
}
  1. 自定义比较函数:如果你有特定的比较逻辑,可以编写自己的比较函数。
代码语言:txt
复制
function areObjectsEqual(obj1, obj2) {
  return _.isEqual(_.toPlainObject(obj1), _.toPlainObject(obj2));
}

应用场景

  • React 组件的 shouldComponentUpdateReact.memo:在这些生命周期方法或高阶组件中使用 _.isEqual 可以避免不必要的渲染。
  • 状态管理库:如 Redux,在比较 action 的 payload 或者 reducer 的 state 时使用 _.isEqual

示例代码

代码语言:txt
复制
import React, { useState } from 'react';
import _ from 'lodash';

function MyComponent({ initialData }) {
  const [data, setData] = useState(initialData);

  const handleUpdate = () => {
    const newData = { ...data, b: data.b + 1 };
    if (!_.isEqual(data, newData)) {
      setData(newData);
    }
  };

  return (
    <div>
      <p>{JSON.stringify(data)}</p>
      <button onClick={handleUpdate}>Update</button>
    </div>
  );
}

在这个示例中,handleUpdate 函数创建了一个新的对象 newData,并使用 _.isEqual 来检查它是否与当前状态 data 不同,如果不同,则更新状态。

通过这些方法,你可以有效地处理在 React 中使用 _.isEqual 时遇到的问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

用 Mongoose 插件记录Node.js API日志

changes(value, base[key]) : value }) } return changes(curr, prev) } 我使用了 lodash,这是一个提供相同功能的受欢迎的库...isEqual:此方法支持比较数组、数组缓冲区、布尔值、日期对象、错误对象、映射、数字、对象、正则表达式、集合、字符串、符号和类型化数组。...对象通过它们自己的方法比较,而不是通过继承的、可枚举的属性进行比较。函数和 DOM 节点则进行严格相等的比较,即使用 ===。 这里我们迭代每个对象的属性和值,并将它与旧对象进行比较。...如果当前对象的 value 不等于前一个对象中相同属性的值:base[key] 如果该值是对象本身,我们递归调用函数changes 直到它得到一个值,它最终将作为 result[key]=value 存储在...它将 document 转换为 Object()和transform:false是为了不允许转换返回对象。

2.8K40
  • Lodash那些“多余”和让人眼前一亮的 API

    亮点:可以传入一个对象进行匹配 console.log(lodash([true, 1, null, 'yes']).every(Boolean)) // false // 等效于 console.log...) partition (站队:根据回调返回值,返回 [ 返回值为true的item数组 , 返回值为false的item数组]) reject (找茬:找出不符合条件的item集合,类似!...克隆系列:clone、cloneDeep、cloneWith、cloneDeepWith eq :判断相等,能判断NaN isEqual :判断两个对象可枚举value相等,注意不能用于对比DOM对象...,'a.b.c.d')) // true console.log(lodash.has(obj2,'a.b.c.d')) // false invert :key-value反转,返回新对象,新对象为旧对象的.../ true console.log(lodash.isEqual(postData1, postData3)) // true pick | pickBy:摘选对象属性,功能和omit |

    3.5K10

    如何让用户选择是否离开当前页面?

    用户选择离开就要继续逻辑,反之则不离开 正式开始 首先要知道一个事件:onbeforeunload,MDN的说明是:当浏览器窗口关闭或者刷新时,会触发beforeunload事件。...当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。...; };` 那么此时我们使用dva/router的history.push方法去跳转前端路由,就不能跳了,因为handlePrompt一直返回false,除非返回ture,否则这个页面通过a标签就无法跳转了...那么很简单,我们使用antd的Modal组件,以及lodash的deepclone(深拷贝)、_.isEqual(value, other)执行深比较来确定两者的值是否相等。...Object 对象值比较自身的属性,不包括继承的和可枚举的属性。 不支持函数和DOM节点比较。

    2.2K30

    React 16.x折腾记 - (6) 基于React 16.x+ Antd 3.x封装的一个声明式的查询组件(实用强大)

    new : 引入lodash的isEqual进行对象深度比对,降低state的合并次数,减少re-render 2018-11-19 : new : 表单提交前,value为空数组不返回,字符串value...[obj] 数据源(构建) accumulate 字符串 超过多少个折叠起来 responseLayout 对象 传递对象,响应式 csize 字符串 控件大小设置,small(小), default(...深比较 import isEqual from 'lodash/isEqual'; // antd const { MonthPicker, RangePicker } = DatePicker;...}); }; // 重置表单 handleReset = () => { this.props.form.resetFields(); // 若是有回调函数,则返回空对象...data.length; i++) { // 若是控件的名字丢.亦或filed的字段名或之值丢失则不渲染该组件 // 若是为select或cascader没有子组件数据也跳过

    16110

    如何高效删除 JavaScript 数组中的重复元素?

    这种方法对于大数组更高效,但存在一些缺点: 类型转换:对象键只能是字符串或符号,这导致数字和字符串形式的数字无法区分。例如,removeDuplicates([1, "1"]) 会返回 [1]。...对象相等性:所有对象在这个解决方案中被认为是相等的。例如,removeDuplicates([{foo: 1}, {foo: 2}]) 会返回 [{foo: 1}]。...即使两个对象内容相同,但引用不同,indexOf 也会返回 -1,导致内容相同但引用不同的对象被认为是不同的。例如,{ foo: 1 } 和另一个 { foo: 1 } 会被当作两个不同的对象。...例如,{ foo: [1, 2] } 和 { foo: [1, 2] } 这样的对象,内容相同但引用不同,会被认为是不同的对象。...存在的问题 对象引用问题:Set 判断元素是否相等时,使用的是同一对象引用。例如,两个内容相同但引用不同的对象 { foo: 1 } 和 { foo: 1 } 会被视为不同的元素。

    14310

    ES6语法翻译Lodash计划:数组篇第3期

    目的是使用ES6语法实现Lodash的单个函数功能,每次分享两个Lodash函数的翻译,涉及到Lodash的类型、字符、数值、数组、对象、函数、集合和工具?。...使用ES6语法翻译Lodash的过程中,有些函数会在ES5语法中存在原型参照,有些比较复杂的函数会翻译成简洁版函数,有些函数可能存在翻译不完整的问题?。...DifferenceBy函数 功能:移除数组中的指定值(使用迭代器) 描述:使用迭代器将数组中被指定数组包含的值移除,返回由剩余值组成的数组 说明:迭代器iterator可认为是map(),将元素格式化后再过滤...Object|Function作为参数,我进行简化翻译,只支持Function DifferenceWith函数 功能:移除数组中的指定值(使用比较器) 描述:使用比较器将数组中被指定数组包含的值移除,返回由剩余值组成的数组...说明:比较器comparator可认为是===(只能对基本数据类型进行全等比较,引用数据类型需自行封装比较器),将元素比较后再过滤 在线演示 备注:比较器可使用_.isEqual,此函数判断全等比较全面

    57620

    React 16.x折腾记 - (7) 基于React+Antd封装聊天记录(用到React的memo,lazy, Suspense这些)

    的isEqual来深度比较对象,用于getDerivedStateFromProps(避免每次都更新state) 代码实现 index.js : 组件的主入口 import React, { PureComponent.../index.css'; // lodash 深比较 import isEqual from 'lodash/isEqual'; // 渲染不同内容的组件 const LazyComponent =...this.state.list]; tmpList.splice(index, 1); this.setState({ list: tmpList }); // 给父的回调,把该item的所有信息返回...( <Popover content={'此操作会删除该记录'}...26&gp=0.jpg' }, 总结 上拉下拉不考虑,因为没这个需求,数据量不大,一个人的留言十几二十多条到顶了 有需要的可以自行添加,也就是多暴露两个事件给外部(判断滚动的高度) 有不对之处请留言,会及时修正

    17110

    React 16.x折腾记 - (8) 基于React+Antd封装选择单个文章分类(从构建到获取)

    前言 随着管理的文章数量增多,默认的几个分类满足不了现状了,趁着重构的过程把相关的功能考虑进去 本来想自己从头写过一个,看了下Antd有内置该类型的控件了,就没必要自己造了 一般自己写,肯定优先考虑数组对象格式...,用气泡悬浮来展示完全的文本 不允许添加同样的(阻止并给予反馈) 默认值初始化并且回馈,把值丢给父 实现 用dva的effect维护接口数据的获取 子组件除了暴露返回值,不做任何涉及Dva这类不纯的东西...import isEqual from 'lodash/isEqual'; export default class DocumentType extends PureComponent { static...inputValue) { this.setState({ inputVisible: false, inputValue: '' }); return false; }...#108ee9" plusBtnText="新的分类" /> ) : null} 总结 不对之处请留言,会及时修正

    12910

    React 折腾记 - (8) 基于React+Antd封装选择单个文章分类(从构建到获取)

    趁着重构的过程把相关的功能考虑进去 本来想自己从头写过一个,看了下Antd有内置该类型的控件了,就没必要自己造了 一般自己写,肯定优先考虑数组对象格式[{tagName:'a',value:1}]; Antd...第一个为默认分类,不允许删除 标签文字过长,则截断,用气泡悬浮来展示完全的文本 不允许添加同样的(阻止并给予反馈) 默认值初始化并且回馈 把值丢给父 实现 用dva的effect维护接口数据的获取 子组件除了暴露返回值...import isEqual from 'lodash/isEqual'; export default class DocumentType extends PureComponent { static...inputValue) { this.setState({ inputVisible: false, inputValue: '' }); return false; }...addTag 添加标签的回调 函数 remvoeTag 移除标签的回调 函数 defaultValue 默认值 字符串 plusBtnText 追加按钮文本替换 字符串 ---- 总结 不对之处请留言,会及时修正

    1.6K40

    前端客户端性能优化实践

    过多的组件渲染会占用大量的内存,并且也会增加页面的渲染时间,自然,响应性能就会变得很差,用户与页面的交互就会变得迟缓。...而没有使用useCallback的情况下,每次组件重新渲染时都会创建一个新的renderContent函数,即使函数的实现逻辑完全相同。这可能会导致性能问题,特别是在组件层级较深或渲染频繁的情况下。...相比之下,如果不使用useMemo,每次组件重新渲染时都会重新计算tooltip的值,即使依赖数组中的值没有发生变化,这样会造成不必要的性能损耗。...} from 'lodash'+ export default React.memo(Item, isEqual)export default Item 直接导出组件,每次父组件重新渲染都会重新渲染...因为每次父组件重新渲染时,knowledge_list都会被重新创建,即使它的值没有发生变化。这样会导致KnowledgeTab组件的props发生变化,从而触发不必要的重新渲染。

    32900

    ‘underscore系列之比较两个元素是否“相同“‘

    那么对于如何判断两个元素是否是相同呢?那么在什么程度上才算是相同, 举个例子: 1与1是相等的(当然他们前提是类型是一样的)那么1和 new Number(1)也应该相等。...第一个条件满足, 我们看第二个 1 / a(-0) === -Infinity而1 / b(0) === Infinity;所以第二个条件也不满足, 那么直接返回return false....关于这里我想了想也对, 如果a === b 直接在上面的判断条件哪里直接就返回了。 所以把return a === b 替换成 retun false, 会更加清晰吧。...所以这里专门针对NaN的情况做了判断, 看case里的第一个判断条件: 如果+a不等于+a那么a就是NaN, 因为NaN === NaN为false。同理b也一样如果b为NaN那么返回为true。...这样就会发现返回true; 当然我觉得布尔类型也是如此, var a = true; var b = new Boolean(false); a为true, 我们也知道true == 1, true

    53820
    领券