Hone logo
Hone
Problems

React Selector Library for State Management

Building a selector library is a crucial skill for managing complex state in React applications, especially when using Redux or other state management solutions. This challenge asks you to create a basic selector library that can efficiently extract and transform data from a given state object. A well-designed selector library promotes code reusability, avoids unnecessary re-renders, and improves the overall maintainability of your application.

Problem Description

You are tasked with creating a TypeScript-based selector library for a simple React application. The application manages a state object with the following structure:

interface State {
  users: {
    id: number;
    name: string;
    email: string;
    isActive: boolean;
  }[];
  settings: {
    theme: 'light' | 'dark';
    language: 'en' | 'es';
  };
  isLoading: boolean;
}

Your selector library should provide the following selectors:

  1. selectUsers: Selects the entire users array from the state.
  2. selectUserSettings: Selects the settings object from the state.
  3. selectIsLoading: Selects the isLoading boolean from the state.
  4. selectActiveUsers: Selects an array containing only the active users (where isActive is true).
  5. selectUserById: Takes a userId (number) as an argument and returns the user object with that ID. If no user with that ID exists, it should return undefined.

The selectors should be memoized using createSelector from reselect to prevent unnecessary re-computations. This means that if the input to a selector hasn't changed, the selector should return the cached result.

Expected Behavior:

  • Selectors should return the correct data based on the current state.
  • selectActiveUsers should filter the users array correctly.
  • selectUserById should return the correct user object or undefined if the user doesn't exist.
  • Selectors should be memoized, meaning they only re-compute when their inputs change.

Examples

Example 1:

// Assume state is:
const state: State = {
  users: [
    { id: 1, name: 'Alice', email: 'alice@example.com', isActive: true },
    { id: 2, name: 'Bob', email: 'bob@example.com', isActive: false },
    { id: 3, name: 'Charlie', email: 'charlie@example.com', isActive: true },
  ],
  settings: { theme: 'light', language: 'en' },
  isLoading: false,
};

// Output of selectActiveUsers(state)
// [
//   { id: 1, name: 'Alice', email: 'alice@example.com', isActive: true },
//   { id: 3, name: 'Charlie', email: 'charlie@example.com', isActive: true },
// ]

// Explanation: The selector filters the users array and returns only the active users.

Example 2:

// Assume state is:
const state: State = {
  users: [
    { id: 1, name: 'Alice', email: 'alice@example.com', isActive: true },
  ],
  settings: { theme: 'dark', language: 'es' },
  isLoading: true,
};

// Output of selectUserById(state, 2)
// undefined

// Explanation: There is no user with ID 2 in the state, so the selector returns undefined.

Example 3:

// Assume state is:
const state: State = {
  users: [],
  settings: { theme: 'light', language: 'en' },
  isLoading: false,
};

// Output of selectActiveUsers(state)
// []

// Explanation: The users array is empty, so the selector returns an empty array.

Constraints

  • You must use reselect for memoization. Install it with npm install reselect.
  • The selectors must be written in TypeScript.
  • The code should be well-structured and easy to understand.
  • The selectUserById selector must handle the case where the user ID does not exist in the users array.
  • Performance is important. Ensure that selectors are memoized to avoid unnecessary re-computations.

Notes

  • Consider using TypeScript generics to make your selectors more type-safe.
  • createSelector takes two arguments: an input selector (which extracts data from the state) and an output selector (which transforms the data).
  • Think about how to efficiently search for a user by ID. A linear search is acceptable for this small example, but in a real-world application, you might consider using a more efficient data structure like a Map.
  • Focus on creating a clean and reusable selector library. This is a fundamental pattern in React development.
Loading editor...
typescript