问题描述
我正在尝试通过使用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 */
}
^请注意,当我说“此内容未更改”时,我指的是内容,而不是引用,因为我确实理解该引用已更改,因为在更改“ project_name”以达到该目标后会进行新的api调用要存储的新数据。但是,由于'requirements'的内容未更改,因此对于lodash的_.isEqual方法,它是否应该评估为true?
我正在使用React Memo。请告知是否有更好的方法来防止重新渲染。我知道深度比较的成本很高,但是我需要防止不必要地重新渲染子组件,因为这会影响性能并导致网站变慢。理想情况下,我只想重新呈现那些已更改的数据部分。
解决方法
道具会有所不同,因为有些标识符在更新时会发生变化。通常用于比较上一个和下一个道具,并防止更快地进行其他渲染。
您是否可以包含其他财产?喜欢比较prevProps.requirements.id
还是使用钩子让您选择反应?
在记录下一个和上一个道具时,您会发现它们不相等,或者在调用JSON.stringify之后记录它们,
我还将重新考虑需要React.memo。 React已经非常擅长于此,并且可以添加更多东西。