Hone logo
Hone
Problems

React Memoization: Optimizing Component Rendering

This challenge focuses on implementing memoization for React components using React.memo. You will create a system that prevents unnecessary re-renders of child components when their props haven't changed, improving application performance. This is a fundamental technique for building efficient React applications.

Problem Description

Your task is to build a React application where you have a parent component and several child components. The parent component will manage some state that, when updated, causes re-renders. You need to strategically use React.memo to optimize the rendering of the child components.

Key Requirements:

  1. Parent Component: This component will hold state (e.g., a counter or a list of items). It will also have a mechanism to update this state.
  2. Child Component(s): Create one or more distinct child components. These child components should receive props from the parent.
  3. Memoization Implementation: Apply React.memo to at least one of the child components.
  4. Demonstrate Optimization: The application should visually or programmatically demonstrate that the memoized component re-renders only when its specific props change, while non-memoized components re-render whenever the parent re-renders (due to unrelated state changes).

Expected Behavior:

  • When the parent component's state updates in a way that does not affect the props passed to the memoized child component, the memoized child should not re-render.
  • When the parent component's state updates in a way that does affect the props passed to the memoized child component, the memoized child should re-render.
  • Non-memoized child components will re-render every time the parent component re-renders, regardless of whether their props have changed.

Edge Cases:

  • Consider how React.memo handles complex prop types like objects and arrays.
  • Think about scenarios where a prop might appear to be the same but is a new reference (e.g., creating a new object or array literal within the parent's render function).

Examples

Example 1: Basic Memoization

Scenario: A parent component with a counter and a child component that displays a static message.

Input (Conceptual):

Parent Component:

  • State: count = 0
  • Button to increment count
  • Child Component: StaticMessage (receives message="Hello, World!")

Output (Behavioral):

  1. Initial Render: StaticMessage renders.
  2. User clicks button to increment count.
  3. Parent re-renders due to count change.
  4. StaticMessage does not re-render because its message prop ("Hello, World!") has not changed.

Example 2: Memoization with Changing Props

Scenario: A parent component with a counter and a child component that displays the counter's value.

Input (Conceptual):

Parent Component:

  • State: count = 0
  • Button to increment count
  • Child Component (Memoized): DisplayCount (receives value={count})

Output (Behavioral):

  1. Initial Render: DisplayCount renders with value=0.
  2. User clicks button to increment count to 1.
  3. Parent re-renders.
  4. DisplayCount does re-render because its value prop (0 -> 1) has changed.

Example 3: Memoization with Unrelated Parent State Change

Scenario: A parent component with two independent states and a child component that depends on only one of them.

Input (Conceptual):

Parent Component:

  • State: count = 0, theme = "light"
  • Button to increment count
  • Button to toggle theme
  • Child Component (Memoized): DisplayCount (receives value={count})

Output (Behavioral):

  1. Initial Render: DisplayCount renders with value=0.
  2. User clicks button to toggle theme (e.g., "light" -> "dark").
  3. Parent re-renders due to theme change.
  4. DisplayCount does not re-render because its value prop (0) has not changed, even though the parent re-rendered due to theme.

Constraints

  • The application must be written in TypeScript.
  • You must use React.memo for at least one child component.
  • The demonstration of optimization can be achieved by adding console.log statements within the child components to indicate when they render.
  • Avoid using useCallback or useMemo in the parent component to create stable prop references for the memoized child unless specifically exploring custom comparison functions. Focus on React.memo's default shallow comparison first.

Notes

  • React.memo performs a shallow comparison of the component's props by default. This means it only checks if primitive prop values have changed or if object/array references are the same.
  • You can optionally provide a custom comparison function as the second argument to React.memo for more complex prop comparisons. While not strictly required for this challenge, it's good to be aware of.
  • Consider how to make your demonstration clear. Adding console.log messages to the rendering logic of your components is a good way to visually track renders in the browser console.
  • Think about the implications of passing objects or functions as props to memoized components. If these are recreated on every render of the parent, memoization might be ineffective.
Loading editor...
typescript