Reactjs React.memo-为什么我的相等函数没有被调用?
我有一个父组件,它根据通过道具接收的数组呈现子组件集合Reactjs React.memo-为什么我的相等函数没有被调用?,reactjs,Reactjs,我有一个父组件,它根据通过道具接收的数组呈现子组件集合 import React from 'react'; import PropTypes from 'prop-types'; import shortid from 'shortid'; import { Content } from 'components-lib'; import Child from '../Child'; const Parent = props => { const { items } = props;
import React from 'react';
import PropTypes from 'prop-types';
import shortid from 'shortid';
import { Content } from 'components-lib';
import Child from '../Child';
const Parent = props => {
const { items } = props;
return (
<Content layout='vflex' padding='s'>
{items.map(parameter => (
<Child parameter={parameter} key={shortid.generate()} />
))}
</Content>
);
};
Parent.propTypes = {
items: PropTypes.array
};
export default Parent;
你知道为什么吗?我不知道你的库的其他部分,但我做了一些更改,你的代码(大部分)似乎正常工作。所以,也许,它可以帮助你缩小原因
简而言之,这种行为的原因在于React的工作方式 React希望每个组件都有一个唯一的密钥,以便跟踪并知道哪个是哪个。通过使用
shortid.generate()
键的一个新值被创建,对组件的引用发生了变化,React认为它是一个全新的组件,需要重新命名
在您的情况下,如果父级中的道具发生任何更改,React将重新渲染所有子级,因为与上一次渲染相比,所有子级的关键点都将不同
希望这有帮助 在子对象上包含标识键属性,并使用
React.memo
(与此特定问题无关,但我认为在此处包含此属性仍然很有用)时,会出现意外渲染的另一种可能性
我认为React只会在儿童
道具上进行diffing。除此之外,children
prop与任何其他属性没有区别。因此,对于此代码,使用myList
而不是children
将导致意外的渲染:
export default props => {
return (
<SomeComponent
myLlist={
props.something.map(
item => (
<SomeItem key={item.id}>
{item.value}
</SomeItem>
)
)
}
/>
)
}
// And then somewhere in the MyComponent source code:
...
{ myList } // Instead of { children }
...
在道具改变之前,它不会记录任何东西。尝试调整父组件中的道具。导入“从“../Child”导入子组件时出错。不确定这是否是原因。如果试图防止子组件不必要的重新加载,则应为每个组件指定唯一的密钥。React有一种非常微妙的处理键的方法,如果组件的键发生变化,React会完全重新启动它。如果您每次生成一个新密钥,React将在父级中的道具更改时重新播放所有内容。@konstantin您是个天才!!我删除了密钥生成,它像一个符咒一样工作!!:D等式fn现在被调用,我可以做比较。谢谢你能把这个作为一个答案,这样我就可以投票选出正确的答案了吗?很高兴我能帮上忙:),现在就把它加上谢谢你花时间创建代码沙盒。我很感激!我的情况有点不同,当您单击按钮时,您正在明确更改属性,这会触发fn。在我的例子中,我只是将一个新项添加到父数组中,每次都创建一个新的子项,并期望触发fn。我刚刚发现问题是我随机生成的关键。
export default props => {
return (
<SomeComponent
myLlist={
props.something.map(
item => (
<SomeItem key={item.id}>
{item.value}
</SomeItem>
)
)
}
/>
)
}
// And then somewhere in the MyComponent source code:
...
{ myList } // Instead of { children }
...
export default props => {
return (
<SomeComponent
children={
props.something.map(
item => (
<SomeItem key={item.id}>
{item.value}
</SomeItem>
)
)
}
/>
)
}
export default props => {
return (
<SomeComponent>
{props.something.map(
item => (
<SomeItem key={item.id}>
{item.value}
</SomeItem>
)
)}
</SomeComponent>
)
}