🔥 🔥 🔥 这些避免 React 组件重复渲染的方法你知道吗?

2025-05-25

🔥 🔥 🔥 这些避免 React 组件重复渲染的方法你知道吗?

使用 React 已经三年了,在这三年里面也沉淀了很多关于 React 代码优化的最佳实践,今天先写一部分出来分享给大家。看看文章热度怎么样,再看看后面的分享。

对于这篇文章中的每个最佳实践,我将提供两个示例,一个好的,一个坏的,以供比较,并提供图像预览.gif

本文主要针对这三种情况进行优化:

  • 父组件更新导致子组件渲染
  • Props 写法错误导致组件渲染
  • 上下文更新导致组件渲染

看完文章如果觉得对您有帮助的话,请帮忙点个赞吧,您的点赞是我创作的最大动力。评论点赞即可获得源码!!!

父组件更新导致子组件渲染

类示例

❎ 错误示例预览

1.classBad.gif

❎ 错误示例

import React, { Component } from "react";
class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  render() {
    const { count } = this.state;
    return (
      <div className="parent">
        <h5>Error Example</h5>
        <p>Parent ComponentCount--{count}</p>
        <button onClick={this.handleClick}>Add</button>
        <Son />
      </div>
    );
  }
}

class Son extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Sub-component re-rendered!!!");
    return <div className="son">Sub-components</div>;
  }
}

export { Parent, Son };

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,父组件的状态改变会导致子组件重新渲染,这是一种非常正常的代码编写方式,但说真的,这仍然会造成性能的浪费,毕竟子组件重新渲染了!接下来,我们看看如何解决这个问题!

注意:这个例子并不意味着不需要写这样的代码,其实优化也是依赖于场景的!

✅ 正确示例 1

import React, { Component, PureComponent } from "react";
class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  render() {
    const { count } = this.state;
    return (
      <div className="parent">
        <h5>Correct example 1</h5>
        <p>Parent ComponentCount--{count}</p>
        <button onClick={this.handleClick}>Add</button>
        <Son />
      </div>
    );
  }
}

class Son extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Sub-component re-rendered!!!");
    return <div className="son">Sub-components</div>;
  }
}

export default Parent;

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中我们主要是借鉴PureComponent来继承这个类,React会自动为我们进行shouldComponentUpdate来对Props进行一个浅比较优化更新。

注意:其实说真的,React 中的组件都是通过 React.createElement(Son) 来执行的,每次执行完之后组件的 Props 引用都是新的,所以会触发重新渲染!

✅ 正确示例 2

import React, { Component } from "react";
class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  render() {
    const { count } = this.state;
    const { children } = this.props;
    return (
      <div className="parent">
        <h5>Correct example 2</h5>
        <p>Parent Component Count--{count}</p>
        <button onClick={this.handleClick}>Add</button>
        {children}
      </div>
    );
  }
}

export default Parent;

<Parent>
  <Son />
</Parent>
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个示例的优化中,我们分离了有状态组件和无状态组件,并使用children来传入无状态组件。这样可以避免无意义的重新渲染!那么,为什么这样写可以避免重新渲染呢?因为在有状态组件中直接使用
children可以避免在有状态组件中使用React.createElement(Son)来渲染子组件!这样做也可以达到优化的目的!

✅ 正确示例 3

import React, { Component, memo } from "react";
import { Son } from "./Bad";

const MemoSon = memo(() => <Son></Son>);

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  render() {
    const { count } = this.state;
    return (
      <div className="parent">
        <h5>Correct example 3</h5>
        <p>Parent Component Count--{count}</p>
        <button onClick={this.handleClick}>Add</button>
        <MemoSon />
      </div>
    );
  }
}

export default Parent;

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

这个例子中,优化的思路和例子1里提到的差不多,我们借用了memo函数,其实它是针对Function组件的一个优化工具。这里我们也厚着脸皮强制用一下!避免重新渲染的思路其实也是比较Props的引用,决定是否渲染!!!

✅ 正确示例 4

import React, { Component, useState, Fragment } from "react";
import { Son } from "./Bad";

const ClickCount = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <Fragment>
      <div>
        <h5>Correct example 4</h5>
        <p>Parent Component Count--{count}</p>
        <button onClick={handleClick}>Add</button>
      </div>
    </Fragment>
  );
};

class Parent extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div className="parent">
        <ClickCount />
        <Son />
      </div>
    );
  }
}

export default Parent;

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们的优化主要是将状态组件移除,合并到一个组件中,这样状态的变化就和子组件分离了,也避免了子组件的重新渲染!

说明:这个优化手段严肃的讲还是用的比较少,看情况使用吧!

Hooks 示例

错误示例预览

1.HooksBad.gif

❎ 错误示例

import { useState } from "react";
const Son = () => {
  console.log("Sub-component re-rendered!!!");
  return <div className="son">Sub-components</div>;
};

const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Error Example</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      <Son />
    </div>
  );
};

export { Son, Parent };
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

对于 Hooks 来说,上面这种写法也非常正常,但相比于 Class 组件,Function 组件有一个特点,就是每次组件重新渲染时,函数都会重新执行一次。对于 Class 组件来说,它只会执行一次new Class,想想其实挺吓人的。而对于函数组件来说,每次执行都意味着新的上下文、新的变量、新的作用域。所以我们需要更加注重函数组件的性能优化。

✅ 正确示例 1

import { useState } from "react";

const Parent = ({ children }) => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Correct example 1</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      {children}
    </div>
  );
};

export default Parent;

<Parent>
  <Son />
</Parent

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们使用children来直接渲染子组件,其原理在上面 Class 组件的例子中已经讲解过。

描述:认真的说,结合函数组件的特点这种优化手段其实是治标不治本!

✅ 正确示例 2

import { useState, useMemo } from "react";
import { Son } from "./Bad";
const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Correct example 2</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      {useMemo(
        () => (
          <Son />
        ),
        []
      )}
    </div>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们使用了优化钩子useMemo,缓存了子组件,只有当依赖项发生变化时,我们才会重新执行该函数来完成重新渲染,否则时间与memoized相同,这有助于避免每次渲染时进行高开销的计算。它还避免了每次都必须在子组件中重新声明变量、函数、作用域等。

注意:我认为这个优化非常出色,因为 useMemo 保存了组件引用,并且不会重新执行函数组件,从而避免了在组件内声明变量、函数和作用域。因此,性能得到了优化。太棒了!

✅ 正确示例 3

import { useState, memo } from "react";
import { Son } from "./Bad";

const SonMemo = memo(Son);

const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Correct example 3</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      <SonMemo />
    </div>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中我们使用了memo这个api ,主要是为了比较props引用是否发生了变化,从而避免子组件的重新渲染!

Props 写法错误导致组件渲染

类示例

❎ 错误示例预览

2.ClassBad.gif

❎ 错误示例

import React, { Component, PureComponent } from "react";

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  render() {
    const { count } = this.state;
    return (
      <div className="parent">
        <h5>Error Example</h5>
        <p>Parent Component Count--{count}</p>
        <button onClick={this.handleClick}>Add</button>
        <Son componentDetails={{ name: "Sub-components" }} anyMethod={() => {}} />
      </div>
    );
  }
}

class Son extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    const { componentDetails, anyMethod } = this.props;
    console.log("Son -> render -> anyMethod", anyMethod);
    console.log("Son -> render -> componentDetails", componentDetails);
    return <div className="son">{componentDetails?.name}</div>;
  }
}

export { Parent, Son };
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

这个例子中 Props 的传递是直接错误的写法。因为组件的渲染主要通过监听 Props 和 State 的变化来渲染,所以这个例子中每次传递的 props 都是一个新的对象,*由于引用不同,每次父组件的渲染都会导致子组件的渲染。*所以这种写法导致的实数重新渲染是不应该的!

那么应该怎么写呢?

✅ 正确示例 1

import React, { Component, PureComponent } from "react";

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      componentDetails: { name: "Sub-components" },
    };
  }
  handleClick = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };
  anyMethod = () => {};
  render() {
    const { count, componentDetails } = this.state;
    return (
      <div className="parent">
        <h5>Correct example 1</h5>
        <p>Parent Component Count--{count}</p>
        <button onClick={this.handleClick}>增加</button>
        <Son componentDetails={componentDetails} anyMethod={this.anyMethod} />
      </div>
    );
  }
}

class Son extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    const { componentDetails, anyMethod } = this.props;
    console.log("Son -> render -> anyMethod", anyMethod);
    console.log("Son -> render -> componentDetails", componentDetails);
    return <div className="son">{componentDetails?.name}</div>;
  }
}

export default Parent;

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

本例主要正确的写法是将变量直接传递给子组件,因为对变量的引用是相同的,所以经过PureComponent检查后,引用并没有发生改变,从而阻止了子组件的渲染!!!

注意:这个有bug的例子严格来说是一个书写问题,导致子组件重新渲染,根本谈不上优化,所以,我们还是禁止写类似有bug的例子那样的代码吧!

Hooks 示例

❎ 错误示例预览

2.HooksBad.gif

❎ 错误示例

import { useState, useEffect } from "react";
const Son = ({ componentDetails, anyMethod }) => {
  useEffect(() => {
    console.log("Son -> componentDetails", componentDetails);
  }, [componentDetails]);
  useEffect(() => {
    console.log("Son -> anyMethod", anyMethod);
  }, [anyMethod]);
  return <div className="son">{componentDetails.name}</div>;
};

const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Error Example</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      <Son componentDetails={{ name: "Sub-components" }} anyMethod={() => {}} />
    </div>
  );
};

export { Son, Parent };

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

这个错误示例,仍然是 props 传递方式的问题!接下来看看如何改正!

✅ 正确示例 1

import { useState, useEffect } from "react";
const Son = ({ componentDetails, anyMethod }) => {
  useEffect(() => {
    console.log("Son -> componentDetails", componentDetails);
  }, [componentDetails]);
  useEffect(() => {
    console.log("Son -> anyMethod", anyMethod);
  }, [anyMethod]);
  return <div className="son">{componentDetails.name}</div>;
};
// This is written for immutable values and can be passed like this
const componentDetails = { name: "Sub-components件" };
const anyMethod = () => {};

const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };
  return (
    <div className="parent">
      <h5>Correct example 1</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      <Son componentDetails={componentDetails} anyMethod={anyMethod} />
    </div>
  );
};

export default Parent;

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们简单地在组件外部引用了不变的值,以确保引用的唯一性,并且不会随着组件的更新而改变。但这种写法有一个局限性,就是它只适用于不变的值。不过,它也有效地避免了组件的重复渲染。

✅ 正确示例 2

import { useState, useEffect, useMemo, useCallback } from "react";
const Son = ({ componentDetails, anyMethod }) => {
  useEffect(() => {
    console.log("Son -> componentDetails", componentDetails);
  }, [componentDetails]);
  useEffect(() => {
    console.log("Son -> anyMethod", anyMethod);
  }, [anyMethod]);
  return <div className="son">{componentDetails.name}</div>;
};

const Parent = () => {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((old) => old + 1);
  };

  const anyMethod = useCallback(() => {}, []);

  const [componentDetails] = useMemo(() => {
    const componentDetails = { name: "Sub-components" };
    return [componentDetails];
  }, []);

  return (
    <div className="parent">
      <h5>Correct example 2</h5>
      <p>Parent Component Count--{count}</p>
      <button onClick={handleClick}>Add</button>
      <Son componentDetails={componentDetails} anyMethod={anyMethod} />
    </div>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

本例中使用了useCallbackuseMemo两个优化钩子,根据依赖项是否发生变化来判断是否更新值的变化,确保值的引用保持不变。这种方式适合大多数的写入,但不宜过度使用,否则代码会非常混乱。

上下文更新导致组件渲染

类示例

❎ 错误示例预览

3.ClassBad.gif

❎ 错误示例

import React, { Component, createContext } from "react";

const contextValue = createContext(undefined);

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      handleIncrement:this.handleIncrement
    };
  }
  handleIncrement = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };

  render() {


    return (
      <contextValue.Provider
        value={this.state}
      >
        <div className="parent">
          <h5>Error Example</h5>
          <Son1 />
          <contextValue.Consumer>
            {(conProps) => <Son2 conProps={conProps} />}
          </contextValue.Consumer>
        </div>
      </contextValue.Provider>
    );
  }
}

class Son1 extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 1 is re-rendered!");
    return <div className="son">Subassembly 1</div>;
  }
}

class Son2 extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 2 is re-rendered!");

    const {
      conProps: { count, handleIncrement },
    } = this.props;
    return (
      <div className="son">
        <p>Subassembly 2--{count}</p>
        <button onClick={handleIncrement}>Add</button>
      </div>
    );
  }
}

export { Parent };
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,如果你仔细观察,你会发现点击子组件 2 中的按钮时,其实是父组件的状态发生了变化,所以问题在于父组件的渲染会导致子组件也渲染。那么,如何避免子组件的重复渲染呢?

✅ 正确示例 1

import React, { Component, createContext } from "react";

const contextValue = createContext(undefined);

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      handleIncrement:this.handleIncrement
    };
  }
  handleIncrement = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };

  render() {
    const { children } = this.props;
    return (
      <contextValue.Provider
        value={this.state}
      >
        <div className="parent">
          <h5>Correct example 1</h5>
          {children}
          <contextValue.Consumer>
            {(conProps) => <Son2 conProps={conProps} />}
          </contextValue.Consumer>
        </div>
      </contextValue.Provider>
    );
  }
}

class Son1 extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 1 is re-rendered!");
    return <div className="son">Subassembly 1</div>;
  }
}

class Son2 extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 2 is re-rendered!");

    const {
      conProps: { count, handleIncrement },
    } = this.props;
    return (
      <div className="son">
        <p>Subassembly 2--{count}</p>
        <button onClick={handleIncrement}>Add</button>
      </div>
    );
  }
}

export { Parent, Son1 };

<Parent>
 <Son1 />
</Parent>

Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们仍然借用了children直接 render的机制,因此父组件中不存在Ract.createElement(Son) api 的执行,因此也就不存在重复渲染!

✅ 正确示例 2

import React, { Component, createContext, PureComponent } from "react";

const contextValue = createContext(undefined);

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      handleIncrement:this.handleIncrement
    };
  }
  handleIncrement = () => {
    const { count } = this.state;
    this.setState({
      count: count + 1,
    });
  };

  render() {
    return (
      <contextValue.Provider
        value={this.state}
      >
        <div className="parent">
          <h5>Correct example 2</h5>
          <Son1 />
          <contextValue.Consumer>
            {(conProps) => <Son2 conProps={conProps} />}
          </contextValue.Consumer>
        </div>
      </contextValue.Provider>
    );
  }
}

class Son1 extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 1 is re-rendered!");
    return <div className="son">Subcomponent 1</div>;
  }
}

class Son2 extends PureComponent {
  constructor(props) {
    super(props);
  }
  render() {
    console.log("Subcomponent 2 is re-rendered!");

    const {
      conProps: { count, handleIncrement },
    } = this.props;
    return (
      <div className="son">
        <p>Subcomponent 2--{count}</p>
        <button onClick={handleIncrement}>Add</button>
      </div>
    );
  }
}

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们主要借用了PureComponent这个类来帮助我们自动进行优化,所以也可以避免重复渲染。

注意:这里你也可以稍微强制使用 React.memo。

Hooks 示例

❎ 错误示例预览

3.HooksBad.gif

❎ 错误示例

import { createContext, useContext } from "react";
import { useCustomReducer } from "../useCustomizeContext";
const CustomizeContext = createContext(undefined);

const Son1 = () => {
  console.log("Subcomponent 1 re-rendered!!!");
  return <div className="son">子组件1</div>;
};
const Son2 = () => {
  const { count, handleIncrement } = useContext(CustomizeContext);
  console.log("Subcomponent 2 re-rendered!!!");
  return (
    <div className="son">
      <p>Subcomponent 2-{count}</p>
      <button onClick={handleIncrement}>Add</button>
    </div>
  );
};

const Parent = () => {
  const value = useCustomReducer({ initValue: 1 });
  return (
    <CustomizeContext.Provider value={value}>
      <div className="parent">
        <h5>Error Example</h5>
        <Son2 />
        <Son1 />
      </div>
    </CustomizeContext.Provider>
  );
};

export { Son1, Parent, Son2 };
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

本例中利用api的createContext,useContext,useReducer实现了一个小的Redux,在子组件2中点击按钮会改变count的值,进而导致值发生变化,于是父组件渲染,导致子组件也随之渲染。

✅ 正确示例 1

import React from "react";
import {
  CustomizeProvider,
  useCustomizeContext,
  useCustomReducer,
} from "../useCustomizeContext";

const Son1 = () => {
  console.log("Subcomponent 1 re-rendered!!!");
  return <div className="son">Subcomponent 1</div>;
};
const Son2 = () => {
  const { count, handleIncrement } = useCustomizeContext();
  console.log("Subcomponent 2 re-rendered!!!");
  return (
    <div className="son">
      <p>Subcomponent 2-{count}</p>
      <button onClick={handleIncrement}>Add</button>
    </div>
  );
};

const Parent = ({ children }) => {
  const value = useCustomReducer({ initValue: 1 });
  return (
    <CustomizeProvider value={value}>
      <div className="parent">
        <h5>Correct example 1</h5>
        <Son2 />
        {children}
      </div>
    </CustomizeProvider>
  );
};
export { Son1 };
export default Parent;


<Parent>
 <Son1 />
</Parent>
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中,我们仍然使用children来解决重复渲染问题。这仍然有效!

描述:事实上,您必须在您的项目中使用正确的优化!

✅ 正确示例 2

import React, { memo } from "react";
import {
  CustomizeProvider,
  useCustomizeContext,
  useCustomReducer,
} from "../useCustomizeContext";

const Son1 = () => {
  console.log("Subcomponent 1 re-rendered!!!");
  return <div className="son">Subcomponent 1</div>;
};
const Son2 = () => {
  const { count, handleIncrement } = useCustomizeContext();
  console.log("Subcomponent 2 re-rendered!!!");
  return (
    <div className="son">
      <p>Subcomponent 2-{count}</p>
      <button onClick={handleIncrement}>Add</button>
    </div>
  );
};
// use memo
const MemoSon1 = memo(Son1);
const Parent = () => {
  const value = useCustomReducer({ initValue: 1 });
  return (
    <CustomizeProvider value={value}>
      <div className="parent">
        <h5>Correct example 2</h5>
        <Son2 />
        <MemoSon1 />
      </div>
    </CustomizeProvider>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

本例中也用到了api memo,还是一样的,比较props的引用是否发生了变化,决定是否更新。

✅ 正确示例 3

import React, { useMemo } from "react";
import {
  CustomizeProvider,
  useCustomizeContext,
  useCustomReducer,
} from "../useCustomizeContext";

const Son1 = () => {
  console.log("Subcomponent 1 re-rendered!!!");
  return <div className="son">Subcomponent 1</div>;
};
const Son2 = () => {
  const { count, handleIncrement } = useCustomizeContext();
  console.log("Subcomponent 2 re-rendered!!!");
  return (
    <div className="son">
      <p>Subcomponent 2-{count}</p>
      <button onClick={handleIncrement}>Add</button>
    </div>
  );
};

const Parent = () => {
  const value = useCustomReducer({ initValue: 1 });
  return (
    <CustomizeProvider value={value}>
      <div className="parent">
        <h5>Correct Example 3</h5>
        <Son2 />
        {useMemo(
          () => (
            <Son1 />
          ),
          []
        )}
      </div>
    </CustomizeProvider>
  );
};

export default Parent;
Enter fullscreen mode Exit fullscreen mode

✋🏻 点击查看在线演示

在这个例子中我们仍然使用useMemo优化钩子来优化组件。

🤙🤙🤙 摘要

本文主要针对三种情况下的优化手段进行阐述,主要使用。

  • 🤙useMemo
  • 🤙备忘录
  • 🤙孩子们
  • 🤙useCallback
  • 🤙PureComponent
  • 🤙提取状态组件
  • 🤙提取常量值

这些优化可用于不同情况,因此如果您在将它们与代码结合使用时,必须使用适当的优化。

如果你还知道其他的优化手段也可以在评论区留下哦!

文章来源:https://dev.to/liujinyi/do-you-know-all-these-means-to-avoid-repeated-rendering-of-react-components-5mf
PREV
如何在 2023 年免费托管你的业余项目:从授权到数据库
NEXT
向我展示你的开源项目 Forem 🌱