尽管使用备忘录并且没有更改任何道具,但仍会在功能组件中重新渲染子项

Sha*_*oux 2 reactjs react-native react-hooks

我有一个 Icon 组件,它绘制一个图标并且它正在闪烁,因为父级正在使其重新渲染。我不明白为什么会发生这种情况以及如何防止这种情况发生。

这是显示问题的小吃

我们使用 setInterval 模拟父更改。

我们通过在控制台中记录“rerender”来模拟图标重新渲染。

这是代码:

import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';


// or any pure javascript modules available in npm
let interval = null

const Child = ({name}) => {
  //Why would this child still rerender, and how to prevent it?
  console.log('rerender')
  return <Text>{name}</Text>
}
const ChildContainer = ({name}) => {
  const Memo = React.memo(Child, () => true)
  return <Memo name={name}/>
}

export default function App() {
  const [state, setState] = React.useState(0)
  const name = 'constant'
  // Change the state every second
  React.useEffect(() => {
    interval = setInterval(() => setState(s => s+1), 1000)
    return () => clearInterval(interval)
  }, [])
  return (
    <View>
      <ChildContainer name={name} />
    </View>
  );
}
Run Code Online (Sandbox Code Playgroud)

如果您能向我解释为什么会发生这种情况以及修复它的正确方法是什么,那就太棒了!

Mic*_*kis 5

如果您移到const Memo = React.memo(Child, () => true)外面,ChildContainer您的代码将按预期工作。

虽然ChildContainer不是记忆化组件,但它会被重新渲染并Child在每个父级重新渲染时创建一个记忆化组件。

通过将 memoization 移到 之外ChildContainer,您可以安全地记住您的组件Child一次,无论ChildContainer调用多少次,Child都只会运行一次。

这是一个工作演示。我还在 上添加了一个日志App来跟踪每次重新渲染,并在 上添加一个日志,ChildComponent以便您可以看到该函数在每次重新渲染时都被调用,而实际上Child不再接触。

你也可以换ChildReact.memo直接:

import * as React from "react";
import { Text, View, StyleSheet } from "react-native";

// or any pure javascript modules available in npm
let interval = null;

const Child = React.memo(({ name }) => {
  //Why would this child still rerender, and how to prevent it?
  console.log("memoized component rerender");
  return <Text>{name}</Text>;
}, () => true);

const ChildContainer = ({ name }) => {
  console.log("ChildContainer component rerender");
  return <Child name={name} />;
};

export default function App() {
  const [state, setState] = React.useState(0);
  const name = "constant";
  // Change the state every second
  React.useEffect(() => {
    interval = setInterval(() => setState(s => s + 1), 1000);
    return () => clearInterval(interval);
  }, []);

  console.log("App rerender");
  return (
    <View>
      <ChildContainer name={name} />
    </View>
  );
}

Run Code Online (Sandbox Code Playgroud)