Bird
Raised Fist0
NextJSframework~20 mins

Repository pattern for data access in NextJS - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Repository Mastery in Next.js
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What does this Next.js repository component render?

Given a repository class that fetches user data, what will the component display?

NextJS
class UserRepository {
  async getUser() {
    return { id: 1, name: 'Alice' };
  }
}

import React, { useEffect, useState } from 'react';

export default function UserProfile() {
  const [user, setUser] = useState(null);
  useEffect(() => {
    const repo = new UserRepository();
    repo.getUser().then(setUser);
  }, []);
  if (!user) return <p>Loading...</p>;
  return <p>{`User: ${user.name}`}</p>;
}
AComponent throws an error
B<p>User: undefined</p>
C<p>Loading...</p> forever
D<p>Loading...</p> initially, then <p>User: Alice</p>
Attempts:
2 left
💡 Hint

Think about when the data is fetched and how state updates.

📝 Syntax
intermediate
2:00remaining
Which option correctly implements a Next.js repository method to fetch posts?

Choose the correct syntax for an async method in a repository class that fetches posts from an API.

NextJS
class PostRepository {
  async fetchPosts() {
    // implementation
  }
}
AfetchPosts() { const res = await fetch('/api/posts'); return res.json(); }
Basync fetchPosts() { const res = await fetch('/api/posts'); return res.json(); }
Casync fetchPosts() { const res = fetch('/api/posts'); return res.json(); }
Dasync fetchPosts() { const res = await fetch('/api/posts'); return res.text(); }
Attempts:
2 left
💡 Hint

Remember to use await with async calls and return the JSON data.

🔧 Debug
advanced
2:00remaining
Why does this Next.js repository method cause a runtime error?

Identify the cause of the error in this repository method.

NextJS
class ProductRepository {
  async getProducts() {
    const response = await fetch('/api/products');
    if (!response.ok) throw new Error('Failed to fetch');
    return response.json;
  }
}
AIt returns response.json instead of calling response.json()
BIt does not check if response.ok is true
Cfetch is missing await keyword
DThe method is not marked async
Attempts:
2 left
💡 Hint

Look carefully at how the JSON data is returned.

❓ state_output
advanced
2:00remaining
What is the state value after this Next.js repository fetch in a React component?

Given this component using a repository, what is the value of data after the effect runs?

NextJS
class CommentRepository {
  async fetchComments() {
    return [{ id: 1, text: 'Hi' }, { id: 2, text: 'Hello' }];
  }
}

import React, { useEffect, useState } from 'react';

export default function Comments() {
  const [data, setData] = useState([]);
  useEffect(() => {
    const repo = new CommentRepository();
    repo.fetchComments().then(setData);
  }, []);
  return null;
}
A[{ id: 1, text: 'Hi' }, { id: 2, text: 'Hello' }]
B[]
Cnull
D[{ id: 1, text: 'Hi' }]
Attempts:
2 left
💡 Hint

Consider what the repository method returns and how state is set.

🧠 Conceptual
expert
2:00remaining
Which statement best describes the benefit of using the repository pattern in Next.js data access?

Choose the most accurate explanation of why the repository pattern is useful in Next.js applications.

AIt replaces React hooks for managing component state with a global store.
BIt automatically caches all API responses to improve performance without extra code.
CIt centralizes data fetching logic, making it easier to maintain and test data access separately from UI components.
DIt forces all data fetching to happen on the server side only, preventing client-side requests.
Attempts:
2 left
💡 Hint

Think about separation of concerns and code organization.

Practice

(1/5)
1. What is the main purpose of using the Repository pattern in a Next.js application?
easy
A. To style components with CSS modules
B. To organize data access in one place for cleaner and reusable code
C. To handle routing between pages
D. To manage component state with hooks

Solution

  1. Step 1: Understand the role of the Repository pattern

    The Repository pattern centralizes data access logic, separating it from UI code.
  2. Step 2: Identify benefits in Next.js context

    This separation makes code cleaner, reusable, and easier to maintain.
  3. Final Answer:

    To organize data access in one place for cleaner and reusable code -> Option B
  4. Quick Check:

    Repository pattern = centralized data access [OK]
Hint: Repository pattern centralizes data access, not UI or styling [OK]
Common Mistakes:
  • Confusing repository with UI state management
  • Thinking repository handles routing
  • Mixing repository with styling concerns
2. Which of the following is the correct way to define a simple repository class in Next.js using TypeScript?
easy
A. class UserRepository { async getAll() { return fetch('/api/users').then(res => res.json()) } }
B. function UserRepository() { return fetch('/api/users') }
C. const UserRepository = () => fetch('/api/users').json()
D. class UserRepository { getAll() { return fetch('/api/users').json() } }

Solution

  1. Step 1: Check class syntax and async usage

    class UserRepository { async getAll() { return fetch('/api/users').then(res => res.json()) } } correctly defines a class with an async method returning parsed JSON from fetch.
  2. Step 2: Identify errors in other options

    function UserRepository() { return fetch('/api/users') } is a function, not a class. const UserRepository = () => fetch('/api/users').json() incorrectly calls .json() directly on fetch result without awaiting. class UserRepository { getAll() { return fetch('/api/users').json() } } misses async and awaits, causing runtime error.
  3. Final Answer:

    class UserRepository { async getAll() { return fetch('/api/users').then(res => res.json()) } } -> Option A
  4. Quick Check:

    Async class method with fetch and json parsing = class UserRepository { async getAll() { return fetch('/api/users').then(res => res.json()) } } [OK]
Hint: Repository methods fetching data must be async and parse JSON [OK]
Common Mistakes:
  • Forgetting async keyword on methods
  • Calling .json() without awaiting fetch response
  • Using function instead of class for repository
3. Given this repository method in Next.js, what will console.log(users) output?
class UserRepository {
  async getAll() {
    return [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
  }
}

const repo = new UserRepository()
const users = await repo.getAll()
console.log(users)
medium
A. [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
B. Promise { <pending> }
C. undefined
D. Error: await is only valid in async function

Solution

  1. Step 1: Analyze the getAll method

    getAll returns a resolved array of user objects immediately (no fetch or delay).
  2. Step 2: Understand await usage

    Await unwraps the Promise returned by async getAll, so users is the array itself.
  3. Final Answer:

    [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] -> Option A
  4. Quick Check:

    Await unwraps async return value = array [OK]
Hint: Await unwraps async method result to actual data [OK]
Common Mistakes:
  • Thinking users is a Promise object
  • Forgetting await causes Promise logged
  • Assuming undefined without return
4. Identify the error in this Next.js repository code snippet:
class ProductRepository {
  getAll() {
    const response = fetch('/api/products')
    return response.json()
  }
}
medium
A. json() method does not exist on response
B. fetch URL is incorrect
C. Missing async keyword and await for fetch and json calls
D. Class name should be lowercase

Solution

  1. Step 1: Check fetch usage

    fetch returns a Promise, so response is a Promise, not the actual response object.
  2. Step 2: Identify missing async/await

    To get JSON data, method must be async and await fetch and response.json() calls.
  3. Final Answer:

    Missing async keyword and await for fetch and json calls -> Option C
  4. Quick Check:

    Async fetch requires await to get response data [OK]
Hint: Always use async/await with fetch and response.json() [OK]
Common Mistakes:
  • Not marking method async
  • Not awaiting fetch or json()
  • Assuming fetch returns data synchronously
5. You want to create a repository in Next.js that fetches user data and caches it to avoid repeated API calls. Which approach correctly applies the repository pattern with caching?
hard
A. class UserRepository { async getAll() { return fetch('/api/users').then(res => res.json()) } }
B. function getAllUsers() { return fetch('/api/users').then(res => res.json()) }
C. const cache = [] async function getAllUsers() { if (cache.length) return cache const res = await fetch('/api/users') cache.push(...await res.json()) return cache }
D. class UserRepository { cache = null async getAll() { if (this.cache) return this.cache const res = await fetch('/api/users') this.cache = await res.json() return this.cache } }

Solution

  1. Step 1: Understand caching in repository context

    Caching should be encapsulated inside the repository class to keep data access logic together.
  2. Step 2: Evaluate options for caching implementation

    class UserRepository { cache = null async getAll() { if (this.cache) return this.cache const res = await fetch('/api/users') this.cache = await res.json() return this.cache } } uses a class property to store cache and returns it if available, avoiding repeated fetch calls.
  3. Step 3: Compare other options

    Options A and B do not implement caching. const cache = [] async function getAllUsers() { if (cache.length) return cache const res = await fetch('/api/users') cache.push(...await res.json()) return cache } uses an external cache variable, breaking encapsulation.
  4. Final Answer:

    class UserRepository { cache = null async getAll() { if (this.cache) return this.cache const res = await fetch('/api/users') this.cache = await res.json() return this.cache } } -> Option D
  5. Quick Check:

    Repository with internal cache property = class UserRepository { cache = null async getAll() { if (this.cache) return this.cache const res = await fetch('/api/users') this.cache = await res.json() return this.cache } } [OK]
Hint: Cache inside repository class to keep data logic together [OK]
Common Mistakes:
  • Caching outside repository breaks encapsulation
  • Not checking cache before fetching
  • Using functions instead of class for caching
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard