Oliver's Blog
  • 🤩Welcome!
  • Projects
    • RISC Game
    • Mini Amazon
    • HTTP Caching Proxy
    • Course Enrollment App
    • Fitness Tracker App
    • Voice Shopping Assistant
    • Graphics Town
  • Algo
    • Binary Search
      • Classical Binary Search
      • First Position of Target
      • Last Position of Target
      • Guess Number Higher or Lower
      • Search in a Big Sorted Array
      • Total Occurrence of Target
      • First Bad Version
      • Find Minimum in Rotated Sorted Array
      • Maximum Number in Mountain Sequence
      • Search a 2D Matrix
      • Search a 2D Matrix II
      • Search for a Range
      • Smallest Rectangle Enclosing Black Pixels
      • Find Peak Element
      • Search in Rotated Sorted Array
      • Wood Cut
      • Find the Duplicate Number
      • Sqrt(x) II
      • Maximum Average Subarray II
      • Copy Books
      • How Many Problem Can I Accept
    • Linked List
      • Insert Node in Sorted Linked List
      • Merge Two Sorted Lists
      • Merge K Sorted Lists
      • LRU Cache
      • Reverse Linked List II
      • Copy List with Random Pointer
      • Reverse Nodes in k-Group
      • Add Two Numbers
      • Swap Nodes in Pairs
      • Rotate List
      • Linked List Cycle
      • Linked List Cycle II
      • Intersection of Two Linked Lists
      • Remove Linked List Elements
      • Reverse Linked List
      • Delete Node in a Linked List
      • Odd Even Linked List
      • Partition List
    • Recursion Basics
      • Fibonacci
      • Double Factorial
      • Reverse Order Storage
      • Linked List Weighted Sum In Reverse Order
    • Binary Tree
      • 1. Traversal
        • Binary Tree Preorder Traversal
        • Binary Tree Inorder Traversal
        • Binary Tree Postorder Traversal
        • Construct Binary Tree from Inorder and Postorder Traversal
        • Minimum Depth of Binary Tree
        • Find Leaves of Binary Tree
        • Reconstruct Itinerary
      • 2. Classical Questions
        • Maximum Depth of Binary Tree
        • Average of Levels in Binary Tree
        • Binary Tree Leaf Sum
        • Invert Binary Tree
        • Binary Tree Path Sum
        • Binary Tree Path Sum II
        • Binary Tree Path Sum III
        • Clone Binary Tree
        • Sum Root to Leaf Numbers
        • Binary Tree Level Sum
        • Binary Tree Paths
      • 3. Binary Search Tree
        • Insert Node in a Binary Search Tree
        • Remove Node in Binary Search Tree
        • Validate Binary Search Tree
        • Trim a Binary Search Tree
        • Search Range in Binary Search Tree
        • Inorder Successor in BST
        • Binary Search Tree Iterator
        • Recover Binary Search Tree
      • 4. Divide and Conquer
        • Balanced Binary Tree
        • Minimum Subtree
        • Subtree with Maximum Average
        • Maximum Subtree
        • Lowest Common Ancestor of a Binary Tree
        • Lowest Common Ancestor II
        • Lowest Common Ancestor III
        • Binary Tree Maximum Path Sum II
        • Binary Tree Maximum Path Sum
        • Path Sum III
      • Convert Sorted Array to Binary Search Tree
      • Path Sum
      • Lowest Common Ancestor of a Binary Search Tree
      • Sum of Left Leaves
      • Minimum Absolute Difference in BST
      • Minimum Distance Between BST Nodes
      • Convert Sorted List to Binary Search Tree
      • Range Sum of BST
      • Kth Smallest Element in a BST
      • Find Largest Value in Each Tree Row
    • Sorting
      • Sort Integers
      • Merge Two Sorted Arrays
      • Reverse Pair
      • Sort List
      • Partition Array
      • Sort Colors
      • Kth Largest Element
      • Multi-keyword Sort
    • Two Pointers
      • Window Sum
      • Two Sum - Difference equals to target
      • Valid Palindrome
      • Remove Duplicates from Sorted Array
      • Recover Rotated Sorted Array
      • Two Sum II - Input array is sorted
      • Two Sum - Unique pairs
      • Two Sum - Closest to target
    • Queue & Stack
      • Implement Queue by Interface
      • Implement Stack
      • Implement Queue by Two Stacks
      • Implement Stack by Two Queues
      • Binary Tree Level Order Traversal
      • Valid Parentheses
      • Min Stack
      • Largest Rectangle in Histogram
      • Evaluate Reverse Polish Notation
      • Implement Queue by Linked List II
      • Basic Calculator II
      • Moving Average from Data Stream
      • Reveal Cards In Increasing Order
      • Longest Valid Parentheses
    • Hash Table
      • Rehashing
      • Valid Anagram
      • Two Sum
      • Contiguous Array
      • Anagrams
      • Remove Duplicate Numbers in Array
      • Friendship Service
    • Heap & Priority Queue
      • Heapify
      • Top k Largest Numbers II
      • K Closest Points
      • Kth Smallest Number in Sorted Matrix
      • Find Median from Data Stream
      • Sliding Window Median
      • Trapping Rain Water II
      • High Five
    • BFS
      • 1. BFS in Binary Tree
        • Check Full Binary Tree
        • Binary Tree Level Order Traversal II
        • Binary Tree Maximum Path Sum II
        • Convert Binary Tree to Linked Lists by Depth
      • 2. Connected Graph & Topologic Sorting
        • Search Graph Nodes
        • Graph Valid Tree
        • Connected Component in Undirected Graph
        • Topological Sorting
        • Course Schedule
        • Course Schedule II
        • Sequence Reconstruction
        • Clone Graph
        • Alien Dictionary
    • Array
      • Remove Element
      • Search Insert Position
      • Maximum Subarray
      • Plus One
      • Merge Sorted Array
      • Pascal's Triangle
      • Pascal's Triangle II
      • Best Time to Buy and Sell Stock
      • Best Time to Buy and Sell Stock II
      • Majority Element
      • Contains Duplicate
      • Contains Duplicate II
      • Summary Ranges
      • Missing Number
      • Move Zeroes
      • Third Maximum Number
      • Binary Search
      • Pairs of Songs With Total Durations Divisible by 60
      • 3Sum
      • Median of Two Sorted Arrays
      • Running Sum of 1d Array
      • Container With Most Water
    • String
      • Longest Substring Without Repeating Characters
      • Roman to Integer
      • Implement strStr()
      • Reverse Words in a String
      • First Unique Character in a String
      • Count Unique Characters of All Substrings of a Given String
    • Math
      • Pow(x, n)
      • Narcissistic Number
      • A + B Problem
    • Dynamic Programming
      • Fibonacci Number
      • N-th Tribonacci Number
      • Climbing Stairs
      • Min Cost Climbing Stairs
    • LeetCode vs. LintCode Table
  • React Notes
    • Optimizing Performance in React
  • Golang Notes
    • Basics
      • Setup
      • Hello World
      • Structure
      • Data Types
      • Variables
      • Operators
      • Constants
      • Decision Making
      • Loops
      • Special Statements
    • Official Tutorial Notes
      • More Types
        • Functions
        • Pointers
        • Structs
        • Arrays
        • Slices
        • Range
        • Maps
        • More Functions
      • Methods and Interfaces
        • Methods
        • Interfaces
        • Stringers
        • Errors
        • Images
        • Readers
      • Concurrency
        • Goroutines
        • Channels
        • Range and Close
        • Select
        • Mutual Exclusion
  • Miscellaneous
    • Traveling to China During a Global Pandemic
Powered by GitBook
On this page
  • Performance Tools in React
  • React-addons-perf
  • Avoid Reconciliation
  • Other hooks
  • Not Mutating Data
  • Code examples
  • Immer
  • Other readings on immutable data

Was this helpful?

  1. React Notes

Optimizing Performance in React

Performance Tools in React

React-addons-perf

import Perf from 'react-addons-perf'; 
Perf.start() 
// App 
Perf.stop()

The Perf methods can be used to take performance measurements.

  • Perf.printInclusive() prints overall time taken.

  • Perf.printExclusive() prints time excluding mounting time

  • Perf.printWasted() prints time wasted on components that didn't actually render anything.

  • Perf.printOperations() prints all DOM manipulations

  • Perf.getLastMeasurements() prints the measurement from the last Perf session.

Avoid Reconciliation

shouldComponentUpdate()

shouldComponentUpdate(nextProps, nextState) {
 return this.props.color !== nextProps.color;
}

Here we use a shallow comparison to determine if the props of the component have changed. If so, the component should update.

React.PureComponent

This is a React component that implements shouldComponentUpdate() and only diffs and updates when it returns true. Any child of PureComponent must also be a PureComponent.

class CounterButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }
  render() {
    return (
      <button
       color={this.props.color}
       onClick={() => this.setState(state => ({count: state.count + 1}))}>
       Count: {this.state.count}
      </button>
    );
  }
}

Other hooks

useReducer

This is an alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method.

Cases to use useReducer over useState:

  1. Complex state logic that involves multiple sub-values

  2. The next state depends on the previous one

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

The dispatch function identity is stable and won't change on re-renders.

useCallback

This returns a memoized callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

Not Mutating Data

Code examples

Consider this example:

class ListOfWords extends React.PureComponent {
  render() {
    return <div>{this.props.words.join(',')}</div>;
  }
}

class WordAdder extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      words: ['hello']
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // This section is bad style and causes a bug
    const words = this.state.words;
    words.push('world');
    this.setState({words: words});
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick} />
        <ListOfWords words={this.state.words} />
      </div>
    );
  }
}

This example creates a bug and "world" is not actually displayed

To solve this problem, we should avoid mutating values that we are using as props or state.

One solution using concat can be:

handleClick() {
  this.setState(state => ({
    words: state.words.concat(['world'])
  }));
}

Or we can use the spread operator in ES6:

handleClick() {
  this.setState(state => ({
    words: [...state.words, 'world'],
  }));
};

For objects, we can also write code to avoid mutating objects. This is the way in which we mutate an object:

function updateColorMap(colormap) {
  colormap.right = 'blue';
}

However, we can avoid mutating the original object using Object.assign in ES6:

function updateColorMap(colormap) {
  return Object.assign({}, colormap, {right: 'blue'});
}

Or, we can use the spread operator for objects from ES2018:

function updateColorMap(colormap) {
  return {...colormap, right: 'blue'};
}

Immer

This is the basic syntax using Immer to avoid mutating data:

import produce from "immer"

const nextState = produce(baseState, draft => {
    draft[1].done = true
    draft.push({title: "Tweet about it"})
})

useState + Immer

import React, { useCallback, useState } from "react";
import produce from "immer";

const TodoList = () => {
  const [todos, setTodos] = useState([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos(
      produce((draft) => {
        const todo = draft.find((todo) => todo.id === id);
        todo.done = !todo.done;
      })
    );
  }, []);

  const handleAdd = useCallback(() => {
    setTodos(
      produce((draft) => {
        draft.push({
          id: "todo_" + Math.random(),
          title: "A new todo",
          done: false
        });
      })
    );
  }, []);

  return (<div>{*/ See CodeSandbox */}</div>)
}

useImmer

import React, { useCallback } from "react";
import { useImmer } from "use-immer";

const TodoList = () => {
  const [todos, setTodos] = useImmer([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos((draft) => {
      const todo = draft.find((todo) => todo.id === id);
      todo.done = !todo.done;
    });
  }, []);

  const handleAdd = useCallback(() => {
    setTodos((draft) => {
      draft.push({
        id: "todo_" + Math.random(),
        title: "A new todo",
        done: false
      });
    });
  }, []);

  // SeeCodeSandbox 

useReducer and Redux + Immer

Similar to useState, Immer also combines with useReducer. And we have useImmerReducer method from the use-immer package.

For Redux + Immer, refer to this doc of Redux Toolkit:

Other readings on immutable data

A few points to note from this article:

  1. Avoid inline function definition in the render function

  2. Avoid using index as key for map

  3. Avoid using props in initial states

  4. Avoid spreading props on DOM elements

  5. Avoid async initialization in componentWillMount()

  6. Memoize React components

PreviousLeetCode vs. LintCode TableNextBasics

Last updated 3 years ago

Was this helpful?

Optimize performance for components that trigger deep updates by

Here is an example on that uses the hook useState and Immer together.

The state updaters have the same pattern, so they can be simplified to using the package.

passing dispatch down instead of callbacks.
CodeSandbox
user-immer
Introduction to Immer | Immer
Logo
GitHub - immerjs/immer: Create the next immutable state by mutating the current oneGitHub
Writing Reducers with Immer | Redux Toolkit
Logo
Immutable Data | Redux
Logo
21 Performance Optimization Techniques for React Appscodementorio
Logo
Efficient React Components: A Guide to Optimizing React PerformanceToptal Engineering Blog
Logo
Logo