DevGang
Авторизоваться

React Props и State: объяснено простым языком

Вы когда-нибудь брали в руки пульт от телевизора? На нем есть кнопки, которые показывают, что воспроизводится в данный момент (например, номер канала), и кнопки, которые позволяют менять то, что воспроизводится.

Компоненты React работают на удивление похоже — некоторые данные они просто отображают, а другие могут изменять. Это, по сути, разница между props и state, но давайте разберем их как следует.

Это две концепции React, которые кажутся опытным разработчикам совершенно понятными, но заставляют остальных из нас чесать затылки.

Даже после просмотра бесчисленных обучающих программ вы все еще можете задаваться вопросом: «Когда мне использовать props? Когда мне использовать state? В чем, собственно, разница?»

К концу этой статьи вы поймете, когда следует использовать props и state, и почему каждый из этих случаев имеет значение!

Сначала основы

Давайте быстро разберемся, зачем они нам вообще нужны. React построен на компонентах — представьте их как блоки LEGO для вашего веб-сайта.

Вы создаете небольшие, многоразовые детали, которые можно соединить вместе, чтобы создать что-то большее. Может быть, это панель навигации, карточка профиля пользователя или просто простая кнопка.

Но вот в чем дело: эти компоненты должны как-то обрабатывать данные. Подумайте о простом компоненте профиля пользователя:

  • Иногда вам нужно передать в него информацию (например, имя пользователя и аватар).
  • Иногда требуется, чтобы компонент управлял собственной информацией (например, открыто или закрыто раскрывающееся меню).

Именно поэтому React предоставляет нам два разных способа обработки данных:

  • Props: Для передачи данных в компоненты
  • State: Для компонентов, управляющих своими собственными данными

Это как разница между:

  • Информация, которую кто-то вам сообщает (props)
  • Информация, которую вы отслеживаете самостоятельно (state)

Вот и все основы. Не нужно усложнять. Давайте перейдем к подробному пониманию.

Props

На самом деле props довольно просты — это просто данные, которые передаются в ваш компонент извне.

Думайте о props как о параметрах функции. Так же, как вы можете передавать аргументы в функцию, вы можете передавать props в компонент. Вот что имеется в виду:

// This is like a function that takes parameters
function Greeting(props) {
  return <h1>Hey {props.name}!</h1>
}

// Using it is as simple as this
<Greeting name="Sarah" />

Вот что вам нужно знать:

  • Реквизиты доступны только для чтения:
  1. Вы не можете изменять props внутри компонента.
  2. Если вы попытаетесь, React на вас накричит (и будет справедливо)
  3. Думайте о них как о входящих сообщениях, которые вы можете читать, но не можете редактировать.
  • Распространенные случаи использования:
  1. Передача текстового содержимого: <Button text="Click Me" />
  2. Конфигурация: <Modal size="large" position="center" />
  3. Передача данных: <UserProfile user={userData} />
  4. Обработка событий: <Button onClick={handleClick} />
  • Props течет вниз
  1. Родительские компоненты передают дочерним компонентам.
  2. Данные передаются только вниз, а не вверх.
  3. Да, это означает, что props представляют собой «односторонний» поток данных.

Короткий пример, чтобы все было предельно ясно:

function UserCard({ name, role, avatar }) {
  return (
    <div>
      <img src={avatar} alt={name} />
      <h2>{name}</h2>
      <p>{role}</p>
    </div>
  );
}

// Using it
<UserCard 
  name="Alex" 
  role="Developer" 
  avatar="/alex.jpg" 
/>

Вот и все, что касается props. Это просто способ передачи данных в компоненты. Вот и все.

State

State — это личная память вашего компонента. В то время как props — это как получение сообщения, state — это как сохранение ваших собственных заметок, которые вы можете обновлять, когда захотите.

Вот ключевая вещь о state: используйте его, когда вашему компоненту нужно отслеживать информацию, которая может измениться. Вот и все.

Давайте посмотрим на это в действии:

import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  )
}

Вот что вам действительно нужно знать о state:

  • Состояние изменчиво:
  1. В отличие от props, вы можете (и должны) обновлять state.
  2. Всегда используйте функцию setter (например setCount)
  3. Никогда не изменяйте состояние напрямую (count = count + 1 это большое табу).
  • Изменения состояния вызывают повторную визуализацию:
  1. При обновлении состояния ваш компонент обновляется.
  2. React сравнивает старое и новое состояние.
  3. В DOM обновляются только измененные части.
  • State — это частное:
  1. Каждый компонент управляет своим собственным состоянием.
  2. Родительские компоненты не могут читать или записывать состояние дочерних компонентов.
  3. Если вам нужно поделиться состоянием, передайте это родителю.

Распространенные варианты использования состояния:

// Form inputs
const [username, setUsername] = useState('')

// Toggles
const [isOpen, setIsOpen] = useState(false)

// Loading states
const [isLoading, setIsLoading] = useState(false)

// Data
const [items, setItems] = useState([])

Помните: если часть данных должна меняться с течением времени — это сигнал к использованию state.

Props против state: основные различия

Давайте разберемся с путаницей и объясним, когда именно следует использовать каждый из них:

Props:

  • Данные, доступные только для чтения и поступающие извне.
  • Не может быть изменено компонентом.
  • Обновлять только тогда, когда родительский элемент перерисовывает.
// Props example
function Header({ username }) {
  return <h1>Welcome {username}</h1>
  // Can't change username here!
}

State:

  • Внутренние данные, которые контролирует компонент.
  • Может (и должен) обновляться компонентом.
  • Обновления запускают повторную визуализацию.
function Menu() {
  const [isOpen, setIsOpen] = useState(false)
  // We control this value!
  return (
    <button onClick={() => setIsOpen(!isOpen)}>
      {isOpen ? 'Close' : 'Open'}
    </button>
  )
}

Распространенные ошибки и передовой опыт

Давайте рассмотрим наиболее распространенные головные боли и способы их предотвращения:

Проблемы с props:

// DON'T do this 🚫
<GrandParent>
  <Parent>
    <Child>
      <GrandChild userProfile={userProfile} />
    </Child>
  </Parent>
</GrandParent>

// DO this instead ✅
// Use React Context or state management for deeply nested data
const UserContext = createContext()
<UserContext.Provider value={userProfile}>
  // Now any child can use useContext(UserContext)
</UserContext.Provider>

Ошибки state:

// DON'T update state directly 🚫
setCount(count + 1)
setCount(count + 1)  // Won't work as expected!

// DO use functional updates ✅
setCount(prev => prev + 1)
setCount(prev => prev + 1)  // Works correctly

Краткие рекомендации:

  • Сохраняйте state настолько локальным, насколько это возможно.
  • Используйте props для потока данных, доступного только для чтения.
  • Разбивайте компоненты, когда они становятся слишком сложными.
  • Используйте контролируемые компоненты для форм.

Практические примеры

Давайте рассмотрим два распространенных сценария, которые эффективно сочетают в себе как props, так и state:

1) Компонент кнопки-переключателя:

function ToggleButton({ initialState, onToggle }) {
  // Local state for the toggle
  const [isOn, setIsOn] = useState(initialState)

  const handleClick = () => {
    setIsOn(!isOn)
    onToggle(!isOn)  // Prop function to notify parent
  }

  return (
    <button 
      onClick={handleClick}
      className={isOn ? 'active' : 'inactive'}
    >
      {isOn ? 'ON' : 'OFF'}
    </button>
  )
}

// Using it
function App() {
  const handleToggle = (state) => {
    console.log('Toggle is now:', state)
  }

  return <ToggleButton 
    initialState={false} 
    onToggle={handleToggle} 
  />
}

2) Компонент карты с state:

function UserCard({ user, onEdit }) {
  // Local state for expand/collapse
  const [isExpanded, setIsExpanded] = useState(false)

  return (
    <div className="card">
      <h3>{user.name}</h3>

      <button onClick={() => setIsExpanded(!isExpanded)}>
        {isExpanded ? 'Show Less' : 'Show More'}
      </button>

      {isExpanded && (
        <div className="details">
          <p>{user.email}</p>
          <p>{user.role}</p>
          <button onClick={() => onEdit(user)}>
            Edit Profile
          </button>
        </div>
      )}
    </div>
  )
}

// Using it
function UserList() {
  const [users, setUsers] = useState([
    { id: 1, name: 'John', email: 'john@example.com', role: 'Admin' }
  ])

  const handleEdit = (user) => {
    // Handle edit logic
  }

  return (
    <div>
      {users.map(user => (
        <UserCard 
          key={user.id}
          user={user}
          onEdit={handleEdit}
        />
      ))}
    </div>
  )
}

Заключение

Давайте подведем итоги и сделаем основные выводы:

Props против state в двух словах:

  • Props: Передача данных, не может быть изменена.
  • State: Память компонента, предназначенная для изменения.

Ментальная модель, которую следует запомнить:

  • Думайте о props как о заказах в ресторане — вы не можете изменить то, что заказал клиент.
  • Подумайте о state как о кухонном инвентаре — кухня контролирует и обновляет его.

Когда и что использовать:

// Use props when:
<UserProfile 
  username={user.name}  // Displaying data
  avatar={user.image}   // Passing configurations
  onSave={handleSave}   // Passing callbacks
/>

// Use state when:
function Form() {
  const [input, setInput] = useState('')         // Form inputs
  const [isValid, setIsValid] = useState(true)   // UI states
  const [data, setData] = useState(null)         // API data
}

Источник:

#React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу