React.memo - 为什么我的相等函数没有被调用?

Joa*_*eis 20 reactjs

我有一个父组件,它根据通过 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;
Run Code Online (Sandbox Code Playgroud)

每次item添加一个新的,所有的孩子都被重新渲染,我试图避免这种情况,我不希望其他孩子被重新渲染,我只想渲染添加的最后一个。

所以我在孩子身上尝试了 React.memo,我可能会通过code属性或其他东西进行比较。问题是等式函数永远不会被调用。

import React from 'react';
import PropTypes from 'prop-types';
import { Content } from 'components-lib';

const areEqual = (prevProps, nextProps) => {
  console.log('passed here') // THIS IS NEVER LOGGED!!
}

const Child = props => {
  const { parameter } = props;
  return <Content>{parameter.code}</Content>;
};

Child.propTypes = {
  parameter: PropTypes.object
};

export default React.memo(Child, areEqual);
Run Code Online (Sandbox Code Playgroud)

任何想法为什么?

Kon*_*tin 13

简而言之,这种行为的原因是由于 React 的工作方式。

React 期望每个组件都有一个唯一的键,以便它可以跟踪并知道哪个是哪个。通过使用shortid.generate()新的键值创建,对组件的引用发生了变化,React 认为它是一个全新的组件,需要重新渲染。

在您的情况下,在父项中的任何道具更改时,React 将重新渲染所有子项,因为与之前的渲染相比,所有子项的键都将不同。

请参考这个主题的精彩答案

希望这可以帮助!


Ott*_*ala 6

我遇到了同样的问题,结果证明解决方案只是一个新手错误。您的子组件必须位于父组件之外。所以而不是:

function App() {
  const [strVar, setStrVar] = useState("My state str");

  const MyChild = React.memo(() => {
    return (
      <Text>
        {strVar}
      </Text>
    )
  }, (prevProps, nextProps) => {
      console.log("Hello"); //Never called
  });

  return (
    <MyChild/>
  )
}
Run Code Online (Sandbox Code Playgroud)

像这样做:

const MyChild = React.memo(({strVar}) => {
  return (
    <Text>
      {strVar}
    </Text>
  )
}, (prevProps, nextProps) => {
   console.log("Hello");
});


function App() {
  const [strVar, setStrVar] = useState("My state str");

  return (
    <MyChild strVar = {strVar}/>
  )
}
Run Code Online (Sandbox Code Playgroud)