DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,155 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for πŸ”₯ πŸ”₯ πŸ”₯ Do you know all these means to avoid repeated rendering of React components?
liu-jin-yi
liu-jin-yi

Posted on

πŸ”₯ πŸ”₯ πŸ”₯ Do you know all these means to avoid repeated rendering of React components?

Use React has been three years, in these three years inside also deposited a lot of best practices on React code optimization, today first write a part out and share with you to share. We'll see if the article is popular and then we'll see if we share the later ones.

For each best practice in this post I will provide two examples, one good and one bad, for comparison, and a preview of the .gif image.

The article in this piece focuses on optimizing these three situations:

  • Parent component update causes child component to render
  • Wrong way of writing Props leads to component rendering
  • Context updates lead to component rendering

After reading the article if you think it has helped you, please help to click a praise, your praise is the biggest motivation for my creation. comment kudos can get the source code!!!

Parent component update causes child component to render

Class Example

❎ Error Example Preview

1.classBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

In this example, a change in the state of the parent component causes the child component to be re-rendered, which is a very normal way to write code, but seriously, it will still cause a waste of performance, after all, the child component is re-rendered! Next, let's see how to solve this problem!

Note: This example does not mean to eliminate the need to write such code, in fact, optimization is also dependent on the scenario!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example we are mainly borrowing from PureComponent to inherit this class, and React will automatically perform shouldComponentUpdate for us to perform a shallow comparison optimization update of Props.

Note: Actually, in all seriousness, components in React are executed by React.createElement(Son), and the resulting component's Props reference is new every time, thus triggering a re-render!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In the optimization of this example, we separate stateful and stateless components and use children to pass stateless components in. This will avoid pointless re-rendering! So why would writing it this way avoid re-rendering? Because using
children directly in the stateful component will avoid using React.createElement(Son) to render the child component in the stateful component! This can also be done to optimize!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, the idea of optimization is similar to the one mentioned in example 1, we borrowed the memo function, which is actually an optimization tool for the Function component We are also cheeky here to force the use of a little! The idea of avoiding re-rendering is actually to compare references to Props as well. Decide whether to render or not !!!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, our optimization is mainly to remove the state component into one component, so that the state change is separated from the child component. It also avoids the re-rendering of the child components!

Description: This optimization means seriously speaking or used quite little, depending on the situation use it!

Hooks Example

Error Example Preview

1.HooksBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

For Hooks the above is also a very normal way of writing, but compared to Class components, Function components have the feature that each time the component is re-rendered, the function is re-executed once. For a Class component, it will only execute new Class once, which is actually quite scary when you think about it. For function components, each execution means a new context, a new variable, and a new scope. So we need to pay more attention to the performance optimization of function components.

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, we use children to render child components directly, the principle of which has been explained in the Class component example above.

Description: Seriously speaking, combining the characteristics of function components this means of optimization is actually a cure for the symptoms, not the root cause!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

n this example we use the optimization Hook useMemo , we cache the Son component and only when the dependency changes we re-execute the function to complete the re-rendering, otherwise the timing is the same memoized, which helps avoid high overhead calculations at each rendering. It also avoids having to redeclare variables, functions, scopes, etc. in the child component each time.

Note: I think this optimization is absolutely brilliant because useMemo saves the component reference and does not re-execute the function component, thus avoiding the declaration of variables, functions, and scopes within the component. Thus, performance is optimized. Nice!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example we use the api memo, mainly to compare whether the props reference has changed, thus avoiding the re-rendering of child components!

Wrong way of writing Props leads to component rendering

Class Example

❎ Error Example Preview

2.ClassBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

The passing of Props in this example is directly wrong way to write it. Because the rendering of the component is mainly rendered by listening to the change of Props and State, that in this example passed props each time is a new object,*because the reference is different, each time the rendering of the parent component will lead to the rendering of the child component. * So the re-rendering of real numbers caused by this writing should not!

So how should we write it?

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

The main correct way to write this example is to pass the variable directly to the child component, because the reference to the variable is the same, so after checking by PureComponent, the reference has not changed, thus preventing the child component from rendering!!!

Note: Strictly speaking, this buggy example is a writing problem that causes re-rendering of subcomponents, so there's no talk of optimization, so let's forbid writing code like the buggy example!

Hooks Example

❎ Error Example Preview

2.HooksBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

In this error example, it is still a problem with the way props are passed! Next see how to correct it!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, we simply refer the invariant value outside the component to ensure that the reference is unique and will not change as the component is updated. But there is a limitation to this way of writing. It is that it is only suitable for invariant values. But it also effectively avoids duplicate rendering of components.

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, two optimization hooks, useCallback and useMemo , are used to determine whether to update a value change based on whether the dependency has changed to ensure that the value reference remains unchanged. This is suitable for most writes, but it should not be overused. Otherwise the code will be very confusing.

Context updates lead to component rendering

Class Example

❎ Error Example Preview

3.ClassBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

In this example, if you look carefully, when you click the button in child component 2,t is the state of the parent component that changes so the problem is that the rendering of the parent component causes the child component to render as well. So how should we avoid duplicate rendering of the child component?

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, we still borrow the mechanism of children o render directly, so there is no Ract.createElement(Son) api execution in the parent component, and therefore no duplicate rendering!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example, we mainly borrow the class PureComponent to help us perform the optimization automatically, so it is also possible to avoid duplicate rendering.

Note: Here you can also force the use of React.memo a bit.

Hooks Example

❎ Error Example Preview

3.HooksBad.gif

❎ Error Example

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

βœ‹πŸ» Click to view online demo

In this example, the api's createContext,useContext,useReducer are used to implement a small Redux, and clicking on the button in child component 2 changes the count value, which in turn causes the value to change, so the parent component renders, causing the child component to follow suit.

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

In this example we are still using children to solve the duplicate rendering problem. This still works!

Description: In fact, you must use the right optimization in your project!

βœ… Correct example 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

βœ‹πŸ» Click to view online demo

The api memo is also used in this example, and is still the same, comparing whether the reference to the props has changed or not, and deciding whether to update it or not.

βœ… Correct Example 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

βœ‹πŸ» Click to view online demo

In this example we still use the useMemo optimization hook to optimize the component.

πŸ€™πŸ€™πŸ€™ Summary

The means of optimization in three cases are described in the article of this piece, mainly the use of.

  • πŸ€™useMemo
  • πŸ€™memo
  • πŸ€™children
  • πŸ€™useCallback
  • πŸ€™PureComponent
  • πŸ€™Extracting status components
  • πŸ€™Extraction of constant values

These optimizations can be used in different situations, so you must use the appropriate optimizations if you are in the process of using them in conjunction with your code.

If you know other means of optimization can also be left in the comments section Oh!

Top comments (13)

Collapse
 
souksyp profile image
Souk Syp.

I used PureComponent for every class component. Is it a bad practice ? 😟

Collapse
 
johnsawiris profile image
John Sawiris

Yes, that is a bad practice what you're doing is premature optimization, and that is the root of all evil.
PureComponent optimize the performance when you have a performe issue; using it without an issue will hinder the performance because every component has to call shouldComponentUpdate and that doesn't happen for free. And functional components are not the answer either, they're not that much different from class components.

Collapse
 
souksyp profile image
Souk Syp.

Okay, thanks! Man need a fix

Collapse
 
liujinyi profile image
liu-jin-yi Author • Edited on

Agree

Collapse
 
lukeshiru profile image
Luke Shiru

You could just use function components instead...

Collapse
 
badpractice profile image
Bad Practice

I'll be the judge of that

Collapse
 
blackr1234 profile image
blackr1234

I use memo for all function components but I always provide the comparison condition.

Collapse
 
efpage profile image
Eckehard

Very impressive demonstration about the stress you get using REACT. What precisely was the advantage of using REACT?

Collapse
 
liujinyi profile image
liu-jin-yi Author

Flexible! Including its powerful ecosystem! and community!

Collapse
 
rammina profile image
Rammina

Thank you for the informative article!

I have heard about useMemo and useCallback before, but I never really got around to using them in my projects. I guess I caused unnecessary rendering.

Collapse
 
liujinyi profile image
liu-jin-yi Author

Thanks for the message! These two Hooks also can not be used too often Oh! And look at the situation flexible use!

Collapse
 
nicolasdanelon profile image
Nicolas Danelon

just a little question... what about prevSrate?
reactjs.org/docs/hooks-reference.h...

Collapse
 
liujinyi profile image
liu-jin-yi Author

Sorry I didn't get your point!

πŸ€” Did you know?

🌚 You can turn on dark mode in Settings