← Назад к вопросам

Как использовать отношения между моделями?

2.0 Middle🔥 121 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Использование отношений между моделями на фронтенде

Отношения между моделями часто встречаются при работе с данными. На фронтенде нужно правильно работать с этими отношениями при запросах к API и управлении состоянием.

Концепция отношений

Отношения между моделями:

  • One-to-Many — один элемент может иметь множество подчинённых (автор имеет много статей)
  • Many-to-One — множество элементов относятся к одному (много статей относятся к одному автору)
  • Many-to-Many — элементы взаимно связаны (студенты и курсы)

Способ 1: Получение данных с вложенными отношениями

Когда API возвращает вложенные данные:

fetch('/api/users/1')
  .then(res => res.json())
  .then(data => {
    console.log(data)
  })

Способ 2: Раздельные запросы для отношений

Иногда API требует отдельные запросы для получения связанных данных:

import { useState, useEffect } from 'react'

export function UserProfile({ userId }) {
  const [user, setUser] = useState(null)
  const [posts, setPosts] = useState([])
  const [loading, setLoading] = useState(true)
  
  useEffect(() => {
    Promise.all([
      fetch(`/api/users/${userId}`).then(r => r.json()),
      fetch(`/api/users/${userId}/posts`).then(r => r.json())
    ])
    .then(([userData, postsData]) => {
      setUser(userData)
      setPosts(postsData)
      setLoading(false)
    })
  }, [userId])
  
  if (loading) return <p>Loading...</p>
  
  return (
    <div>
      <h1>{user.name}</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

Способ 3: Нормализация данных

При работе с большим количеством отношений полезно нормализовать данные:

const normalized = {
  users: {
    1: { id: 1, name: 'John', postIds: [1, 2] }
  },
  posts: {
    1: { id: 1, title: 'Post 1', authorId: 1 },
    2: { id: 2, title: 'Post 2', authorId: 1 }
  }
}

const getUserWithPosts = (userId) => {
  const user = normalized.users[userId]
  const posts = user.postIds.map(postId => normalized.posts[postId])
  return { ...user, posts }
}

Способ 4: Many-to-Many отношения

При many-to-many отношениях элементы взаимно связаны:

const courseData = {
  id: 1,
  title: 'React Basics',
  studentIds: [1, 2, 3]
}

export function CourseEnrollment({ courseId, studentId }) {
  const [enrolled, setEnrolled] = useState(false)
  
  const enrollStudent = async () => {
    const response = await fetch(`/api/courses/${courseId}/enroll`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ studentId })
    })
    
    if (response.ok) {
      setEnrolled(true)
    }
  }
  
  return (
    <button onClick={enrollStudent} disabled={enrolled}>
      {enrolled ? 'Enrolled' : 'Enroll'}
    </button>
  )
}

Способ 5: Использование библиотек

Сложные отношения проще управлять с библиотеками для нормализации:

import { normalize, schema } from 'normalizr'

const user = new schema.Entity('users')
const post = new schema.Entity('posts', {
  author: user
})

const mySchema = [post]

const data = [
  {
    id: 1,
    title: 'Post 1',
    author: { id: 1, name: 'John' }
  }
]

const normalized = normalize(data, mySchema)

Способ 6: React Query для управления отношениями

Современные библиотеки упрощают работу с отношениями:

import { useQuery } from '@tanstack/react-query'

export function UserProfile({ userId }) {
  const { data: user, isLoading } = useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json())
  })
  
  const { data: posts } = useQuery({
    queryKey: ['posts', userId],
    queryFn: () => fetch(`/api/users/${userId}/posts`).then(r => r.json()),
    enabled: !!user
  })
  
  if (isLoading) return <p>Loading...</p>
  
  return (
    <div>
      <h1>{user.name}</h1>
      <ul>
        {posts?.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  )
}

Ключевые моменты

  • Вложенные данные — API может возвращать отношения в одном запросе
  • Раздельные запросы — используй Promise.all для параллельных запросов
  • Нормализация — избегай дублирования данных в состоянии
  • Many-to-Many — управляй связями через ID массивы
  • Библиотеки — normalizr, React Query упрощают работу с отношениями

Правильная работа с отношениями между моделями критична для эффективного управления сложными данными.

Как использовать отношения между моделями? | PrepBro