Hone logo
Hone
Problems

Building a Context System in React with TypeScript

Context systems in React provide a way to share data between components without explicitly passing props through every level of the component tree. This challenge asks you to build a simplified context system from scratch, allowing you to understand the underlying mechanisms and gain a deeper appreciation for React's built-in Context API. This is a valuable exercise for solidifying your understanding of React's core concepts and functional programming principles.

Problem Description

You are tasked with creating a basic context system in React using TypeScript. This system should allow components to:

  1. Provide: A component can "provide" a value to the context.
  2. Consume: Other components can "consume" the value provided by the context.

The context system should be implemented as a set of functions and React components. You don't need to replicate all the features of React's built-in Context API (e.g., memoization, complex update strategies), but the core functionality of providing and consuming a value should be present.

Key Requirements:

  • createContext<T>: A function that creates a new context. T represents the type of the context value.
  • Provider Component: A React component that accepts a value prop and makes that value available to consuming components.
  • useContext Hook: A custom hook that accepts a context object and returns the current context value.

Expected Behavior:

  • Components wrapped in a Provider should receive the value provided by the Provider.
  • Components not wrapped in a Provider should receive a default value (you can choose a sensible default, like undefined).
  • Changes to the value prop of the Provider should trigger re-renders in consuming components.

Edge Cases to Consider:

  • What happens when a component tries to consume a context that is not provided anywhere in its ancestry?
  • How will you handle type safety with the generic T?
  • Consider how updates to the context value will trigger re-renders.

Examples

Example 1:

Input:
```typescript
const MyContext = createContext<string | null>(null);

function App() {
  return (
    <MyContext.Provider value="Hello, Context!">
      <ComponentA />
    </MyContext.Provider>
  );
}

function ComponentA() {
  const value = useContext(MyContext);
  return <div>Value: {value}</div>;
}
Output:
<div>Value: Hello, Context!</div>
Explanation: ComponentA consumes the context value "Hello, Context!" provided by the MyContext.Provider.

Example 2:

Input:
```typescript
const MyContext = createContext<number>(0);

function App() {
  return (
    <MyContext.Provider value={42}>
      <ComponentB />
      <ComponentC />
    </MyContext.Provider>
  );
}

function ComponentB() {
  const value = useContext(MyContext);
  return <div>Value in B: {value}</div>;
}

function ComponentC() {
  const value = useContext(MyContext);
  return <div>Value in C: {value}</div>;
}
Output:
<div>Value in B: 42</div>
<div>Value in C: 42</div>
Explanation: Both ComponentB and ComponentC consume the same context value (42) provided by the MyContext.Provider.

Example 3: (Edge Case)

Input:
```typescript
const MyContext = createContext<boolean>(false);

function App() {
  return <ComponentD />;
}

function ComponentD() {
  const value = useContext(MyContext);
  return <div>Value in D: {value}</div>;
}
Output:
<div>Value in D: false</div>
Explanation: ComponentD is not wrapped in a Provider, so it receives the default value (false) defined in createContext.

Constraints

  • No external libraries: You must implement the context system using only React and TypeScript. Do not use React's built-in useContext or createContext hooks.
  • Type Safety: The createContext<T> function must be generic and enforce type safety for the context value.
  • Re-renders: Changes to the value prop of the Provider should trigger re-renders in consuming components. While full memoization isn't required, ensure the re-renders are reasonable.
  • Performance: While not a primary focus, avoid unnecessary re-renders.

Notes

  • Think about how you can use React's useState or similar mechanisms to track context changes and trigger updates.
  • Consider how to manage the context object itself and how to associate it with the Provider and useContext hook.
  • This is a simplified context system. React's built-in Context API has additional features and optimizations that are not required for this challenge. Focus on the core concepts of providing and consuming a value.
  • Start by implementing createContext<T> and the Provider component. Then, implement the useContext hook. Test each component thoroughly as you build it.
Loading editor...
typescript