0
0
NextJSframework~5 mins

Repository pattern for data access in NextJS

Choose your learning style9 modes available
Introduction

The repository pattern helps organize how your app talks to data sources. It keeps data access code in one place, making your app easier to manage and change.

When you want to keep your data fetching logic separate from UI code.
When you might switch data sources later, like from a local file to a database.
When you want to reuse data access code in different parts of your app.
When you want to make testing easier by mocking data access.
When your app grows and data handling becomes more complex.
Syntax
NextJS
class Repository {
  async getAll() {
    // fetch all items
  }

  async getById(id) {
    // fetch one item by id
  }

  async create(data) {
    // add new item
  }

  async update(id, data) {
    // update item by id
  }

  async delete(id) {
    // delete item by id
  }
}

This is a simple class with methods to get, add, update, and delete data.

Each method is async because data fetching usually takes time.

Examples
A repository class fetching all users from an API endpoint.
NextJS
class UserRepository {
  async getAllUsers() {
    return fetch('/api/users').then(res => res.json())
  }
}
Fetches a single product by its ID using a dynamic URL.
NextJS
class ProductRepository {
  async getProductById(id) {
    return fetch(`/api/products/${id}`).then(res => res.json())
  }
}
Creates a new todo item by sending a POST request with JSON data.
NextJS
class TodoRepository {
  async createTodo(todo) {
    return fetch('/api/todos', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(todo)
    }).then(res => res.json())
  }
}
Sample Program

This React component uses a UserRepository class to get user data. It shows a list of user names after fetching them asynchronously.

The repository hides the data fetching details from the component, keeping code clean.

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

class UserRepository {
  async getAllUsers() {
    // Simulate fetching data
    return new Promise(resolve => {
      setTimeout(() => {
        resolve([
          { id: 1, name: 'Alice' },
          { id: 2, name: 'Bob' }
        ])
      }, 500)
    })
  }
}

export default function UserList() {
  const [users, setUsers] = useState([])
  const repo = new UserRepository()

  useEffect(() => {
    repo.getAllUsers().then(data => setUsers(data))
  }, [])

  return (
    <main>
      <h1>User List</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </main>
  )
}
OutputSuccess
Important Notes

Keep repository methods focused on data access only, not UI logic.

Use async/await or promises to handle asynchronous data fetching.

Repositories make it easier to change data sources without changing UI code.

Summary

The repository pattern organizes data access in one place.

It helps keep UI code clean and easier to maintain.

Use it when you want reusable, testable, and flexible data handling.