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



我正试图通过使用React Memo来阻止我的子组件的重新发布。然而,由于react memo使用浅比较,我尝试引入lodash_.isEqual方法,以便进行深度比较,以防止在对象的值不变的情况下重新发送。但是,即使对象的值没有更改,它也会返回false。有什么原因吗?我会明白,如果比较是浅的,因为对象引用是不同的,但为什么深度比较会返回false?

这是我的代码

import React, { useState } from 'react'
import { Button, Empty, List, Spin, Menu, Dropdown, Skeleton } from 'antd';
import OpportunityDrawer from './Forms/OpportunityDrawer';
import { FileImageOutlined, MoreOutlined, MailOutlined, IdcardOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux'
import RequirementHistory from './RequirementHistory';
const _ = require("lodash");
function RequirementTimeline({ requirements }) {

const actions = (requirement) => (
<Menu>
<Menu.Item>
<OpportunityDrawer data={requirement}
button_name='Edit Requirement'
title='Edit Requirement'
component='RequirementUpdate'
button_type='update' />
</Menu.Item>
<Menu.Item><OpportunityDrawer data={requirement.customer_requirement_id}
button_name='Delete Requirement'
title='Delete Requirement'
component='RequirementDelete'
button_type='delete' /></Menu.Item>
{requirement.file ?
<Menu.Item>
<Button type="text" shape="circle" size="small"><a href={requirement.file}><FileImageOutlined /></a></Button> File
</Menu.Item>
: null}
<Menu.Item><RequirementHistory history={requirement.history} /></Menu.Item>
<Menu.Item><CalendarDrawer
button_name='Create Reminder'
title='When Shall we remind you?'
component='CreateReminder'
task_title={`Reminder [Requirements ID: ${requirement.customer_requirement_id}]`}
content={`Please remember to follow up on Requirement [${requirement.customer_requirement_id}]`}
/>
</Menu.Item>
</Menu>
)
console.log('hi')
return (
requirements.length ?
<List
size="large"
dataSource={requirements}
renderItem={item => (
<List.Item>
<div className='requirement-grid'>
<p className='requirement-title'><MailOutlined />{item.requirements}</p>
<p className='requirement-description'><IdcardOutlined /> ID: {item.customer_requirement_id}</p>
<Dropdown placement="bottomRight" overlay={() => actions(item)}>
<Button size='small' shape='circle' className='requirement-button'><MoreOutlined /></Button>
</Dropdown>
</div>
</List.Item>
)}
/>
: <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
)
}
export default React.memo(RequirementTimeline,
(prevProps, nextProps) => {
console.log(_.isEqual(prevProps.requirements, nextProps.requirements));
return _.isEqual(prevProps.requirements, nextProps.requirements)
})

本质上,需求道具的内容不会改变。在父组件中,数据会更改,但作为数据一部分的嵌套对象"requirement"不会更改。

例如,我所做的是更新数据的另一部分,同时保持"需求"的内容不变。

{ project_name: /* this is changed */ ,
requirements: [ /* this is not changed */
}

^请注意,当我说"this is not changed"时,我指的是内容,而不是引用,因为我确实理解引用已更改,因为在更改"project_name"后会进行新的api调用,以获得要存储的新数据。然而,既然"requirements"的内容没有改变,那么对于lodash的_.isEqual方法,它不应该被评估为true吗?

我正在使用React Memo。如果有更好的方法来防止再次出现,一定要提出建议。我知道深度比较是昂贵的,但我需要防止子组件不必要地重新渲染,因为这会阻碍性能并导致网站速度减慢。理想情况下,我只想重新发送数据中发生更改的部分。

道具会有所不同,因为更新时会更改标识符。它通常用于比较上一个道具和下一个道具,并更快地防止额外的渲染。

你还有其他可以包括在内的财产吗?喜欢比较prevProps.requirements.id还是用钩子让react为你挑选?

当您记录next和prev道具时,您可以看到它们不相等,或者如果您在调用JSON.stringify、后记录它们

我也会重新考虑是否需要React.memo。React在这方面已经很擅长了,添加额外的东西可以开始。

最新更新