React

Бизюк Андрей

ВГТУ

2024-12-03

Введение в React

Обзор React

React - это библиотека JavaScript, разработанная компанией Facebook, предназначенная для создания интерактивных пользовательских интерфейсов. С помощью React разработчики могут создавать компоненты пользовательского интерфейса, которые являются независимыми и могут быть повторно использованы в различных частях приложения. React использует концепцию виртуального DOM для эффективного обновления пользовательского интерфейса, что приводит к улучшенной производительности веб-приложений.

Краткая история развития React

  • React был разработан компанией Facebook и впервые был представлен в 2013 году.
  • Вначале React использовался внутренне в Facebook для улучшения производительности и эффективности разработки интерфейсов.
  • В 2013 году React был открыт исходный код, и стал доступен для широкой общественности как проект с открытым исходным кодом.
  • С течением времени React стал популярным инструментом для разработки веб-приложений, используемых не только Facebook, но и многими другими компаниями и разработчиками по всему миру.
  • React активно развивается и поддерживается сообществом разработчиков. Регулярно выпускаются новые версии с улучшениями и новыми функциями.

Причины популярности

  • Простота и эффективность: React предлагает простой и эффективный подход к созданию пользовательского интерфейса с помощью компонентов и виртуального DOM.
  • Удобство повторного использования: Компоненты React могут быть легко повторно использованы в различных частях приложения, что способствует улучшению поддерживаемости и разработки.
  • Производительность: Благодаря использованию виртуального DOM и эффективному алгоритму обновления, React обеспечивает высокую производительность даже для крупных и сложных веб-приложений.
  • Большое сообщество и экосистема: React имеет огромное сообщество разработчиков, а также обширную экосистему инструментов, библиотек и ресурсов для разработки, что делает его привлекательным выбором для многих разработчиков.
  • Поддержка корпоративных проектов: Множество крупных компаний используют React в своих проектах, что гарантирует его стабильность, поддержку и долгосрочную перспективу развития.
  • Хорошо документирован и поддерживается: React обладает обширной документацией, учебными материалами и активным сообществом, что делает его легким для изучения и использования разработчиками всех уровней навыков.

Создание нового приложения React

npm

npm (Node Package Manager) - это менеджер пакетов для языка программирования JavaScript, в первую очередь используемый для управления модулями Node.js. npm устанавливается вместе с Node.js, что означает, что при загрузке Node.js вы автоматически получаете установленный npm на вашей системе.

npm позволяет разработчикам устанавливать, обмениваться и управлять зависимостями или пакетами для их проектов Node.js. Он также предоставляет интерфейс командной строки, который позволяет разработчикам взаимодействовать с npm для выполнения различных задач, таких как установка пакетов, обновление пакетов, управление зависимостями и запуск скриптов, определенных в файле package.json проекта.

Некоторые распространенные команды npm включают в себя:

  • npm install: Устанавливает зависимости, перечисленные в файле package.json.
  • npm install <package-name>: Устанавливает определенный пакет локально.
  • npm install -g <package-name>: Устанавливает пакет глобально.
  • npm update: Обновляет пакеты до их последних версий на основе диапазонов версий, указанных в файле package.json.
  • npm uninstall <package-name>: Удаляет пакет.
  • npm search <keyword>: Поиск пакетов в реестре npm.
  • npm init: Инициализирует новый проект Node.js и создает файл package.json.
  • npm start: Запускает скрипт “start”, определенный в файле package.json.
  • npm test: Запускает скрипт “test”, определенный в файле package.json.

Использование CDN версии React

Создадим HTML файл со следующим содержимым:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

    <!-- Don't use this in production: -->
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
    
      function MyApp() {
        return <h1>Hello, world!</h1>;
      }

      const container = document.getElementById('root');
      const root = ReactDOM.createRoot(container);
      root.render(<MyApp />);

    </script>
    <!--
      Note: this page is a great way to try React but it's not suitable for production.
      It slowly compiles JSX with Babel in the browser and uses a large development build of React.

      Read this page for starting a new React project with JSX:
      https://react.dev/learn/start-a-new-react-project

      Read this page for adding React with JSX to an existing project:
      https://react.dev/learn/add-react-to-an-existing-project
    -->
  </body>
</html>

Этот файл можно использовать для того, чтобы попробовать React без необходимости что-либо устанавливать. Но такой вариант будет очень медленным и не подходит для реального использования.

Создание и запуск приложения с помощью create-react-app (устарело)

Давайте создадим новое приложение React с использованием Create React App, который является одним из наиболее распространенных способов начать новый проект React. Вам потребуется установленный Node.js для этого.

Шаги:

  1. Установите Create React App, выполнив следующую команду в терминале (если вы еще этого не сделали):

    npm install -g create-react-app
  2. Создайте новое приложение, выполните:

    npx create-react-app my-app

    Замените my-app на имя вашего приложения.

  3. Перейдите в каталог вашего нового приложения:

    cd my-app
  4. Запустите приложение:

    npm start

Это запустит разработческий сервер, и ваше новое приложение будет доступно по адресу http://localhost:3000/.

Теперь ваше новое приложение React готово к использованию! Вы можете редактировать файлы в каталоге src для создания своего приложения, добавлять новые компоненты, стили и многое другое.

Создание React приложения с использованием фреймворка Next.js

Для создания React-приложения с использованием Next.js, вам следует выполнить следующие шаги:

  1. Установка Node.js и npm: Убедитесь, что у вас установлен Node.js и npm на вашем компьютере. Вы можете загрузить их с официального сайта Node.js: nodejs.org.

  2. Создание нового проекта Next.js: Выполните следующие команды в вашем терминале или командной строке, чтобы создать новый проект Next.js:

    npx create-next-app my-next-app

    Где my-next-app - это название вашего проекта. Эта команда создаст новый каталог my-next-app и установит в него структуру проекта Next.js.

  3. Запуск проекта: После того, как проект был создан, перейдите в каталог проекта:

    cd my-next-app

    И затем запустите проект с помощью следующей команды:

    npm run dev

    Это запустит Next.js в режиме разработки. По умолчанию ваше приложение будет доступно по адресу http://localhost:3000.

  4. Начните разработку: Теперь вы можете начать разрабатывать свое приложение. Файлы React-компонентов можно создавать в каталоге pages. Каждый файл в этом каталоге становится маршрутом в вашем приложении.

    Например, создайте файл pages/index.js с содержимым:

    function HomePage() {
      return (
        <div>
          <h1>Hello, Next.js!</h1>
        </div>
      );
    }
    
    export default HomePage;

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

Это основы создания React-приложения с использованием Next.js. Можно найти дополнительную информацию и руководства на официальном сайте Next.js: nextjs.org/docs.

Компоненты в React

Что такое компоненты в React и почему они важны

Компоненты в React представляют собой независимые блоки пользовательского интерфейса, которые объединяют в себе логику и отображение. Они используются для создания интерактивных элементов на веб-страницах. Компоненты позволяют разбить сложный интерфейс на более мелкие, самодостаточные части, что делает код более организованным, повторно используемым и легким для поддержки и расширения. Компоненты также позволяют упростить разработку, так как различные части интерфейса могут быть разработаны и отлажены независимо друг от друга.

Различие между функциональными и классовыми компонентами

  1. Функциональные компоненты:
    • Это функции JavaScript, которые принимают входные данные (props) и возвращают React-элементы, которые описывают, что нужно отобразить на экране.
    • Начиная с React 16.8, функциональные компоненты также могут использовать хуки (hooks) для работы с состоянием и другими возможностями React.
    • Функциональные компоненты обычно более просты в написании и понимании.
  2. Классовые компоненты:
    • Это классы JavaScript, которые расширяют базовый класс React.Component.
    • Классовые компоненты имеют состояние и методы жизненного цикла (например, componentDidMount, componentDidUpdate).
    • Ранее, до появления хуков, классовые компоненты использовались для работы с состоянием и жизненным циклом, но теперь они используются реже из-за более удобного синтаксиса функциональных компонентов с хуками.

Примеры компонентов и их роли в структуре приложения

  1. Кнопка:
    • Простой компонент, который отображает кнопку на экране.
    • Может принимать свойства, такие как текст на кнопке или функцию обратного вызова для обработки событий нажатия.
  2. Форма:
    • Компонент, который содержит поля ввода и кнопку отправки для ввода данных пользователем.
    • Обрабатывает данные, введенные пользователем, и отправляет их на сервер.
  3. Список элементов:
    • Компонент, который отображает список элементов на экране, например, список задач или контактов.
    • Может принимать массив данных и отображать каждый элемент списка в виде отдельного компонента.
  4. Меню навигации:
    • Компонент, который содержит ссылки на различные страницы или разделы приложения.
    • Отображает навигационное меню и обрабатывает переходы между страницами.

JSX

Что такое JSX и как он используется в React

JSX (JavaScript XML) - это расширение синтаксиса JavaScript, которое позволяет писать код, похожий на HTML, непосредственно в JavaScript. JSX используется в React для определения структуры пользовательского интерфейса, то есть для описания того, как компоненты должны быть отображены на экране. JSX делает код более читаемым и понятным, а также упрощает работу с элементами интерфейса.

Пример использования JSX в React:

import React from 'react';

const MyComponent = () => {
  return (
    <div>
      <h1>Hello, World!</h1>
      <p>This is a JSX element.</p>
    </div>
  );
}

export default MyComponent;

Основные принципы синтаксиса JSX

  1. Теги: JSX использует синтаксис тегов, похожий на HTML, для определения элементов. Теги могут быть самозакрывающимися, как <input />, или иметь соответствующие открывающие и закрывающие теги, как <div></div>.

  2. Вложенность: Элементы JSX могут быть вложенными друг в друга, как в HTML.

  3. JavaScript выражения: Внутри JSX можно использовать JavaScript выражения, заключая их в фигурные скобки {}. Это позволяет вставлять переменные, вызовы функций и другие выражения прямо в JSX.

  4. Стили и атрибуты: Атрибуты элементов JSX можно определять так же, как в HTML. Для определения стилей используется объект JavaScript в атрибуте style.

  5. Комментарии: Комментарии в JSX должны быть заключены в фигурные скобки {/* */}.

Преимущества и недостатки использования JSX

Преимущества:

  • Читаемость и понятность: JSX делает код более читаемым и понятным, особенно для разработчиков, знакомых с HTML.

  • Интеграция JavaScript: JSX позволяет использовать JavaScript выражения непосредственно внутри разметки, что упрощает взаимодействие с данными и логикой приложения.

  • Статические анализаторы кода: JSX позволяет статическим анализаторам кода, таким как ESLint, предоставлять дополнительные проверки и подсказки.

Недостатки:

  • Новый синтаксис: Для некоторых разработчиков JSX может быть новым и необычным синтаксисом, требующим времени для освоения.

  • Необходимость компиляции: Браузеры не могут напрямую интерпретировать JSX, поэтому код на JSX требует предварительной компиляции в JavaScript с помощью инструментов, таких как Babel.

  • Вероятность возникновения ошибок: Неправильное использование JSX может привести к ошибкам, особенно при вставке JavaScript выражений.

Виртуальный DOM

Концепция виртуального DOM в React

Виртуальный DOM (VDOM) - это концепция, используемая в React для улучшения производительности обновления пользовательского интерфейса. Вместо того чтобы напрямую обновлять реальный DOM при каждом изменении данных, React создает в памяти виртуальное представление DOM. Это виртуальное дерево DOM содержит копию текущего состояния интерфейса и позволяет React определить минимальное количество манипуляций DOM, необходимых для обновления интерфейса.

Как работает процесс обновления DOM в React

  1. Изменение состояния: Когда состояние компонента React изменяется (например, пользователь вводит данные в форму или происходит получение данных с сервера), React создает новое виртуальное дерево DOM на основе измененного состояния.

  2. Сравнение виртуального DOM: React сравнивает новое виртуальное дерево DOM с предыдущим, сохраненным в памяти. Он анализирует различия между ними, чтобы определить, какие части интерфейса были изменены.

  3. Вычисление минимальных изменений: React вычисляет минимальное количество манипуляций DOM, необходимых для того, чтобы применить изменения из нового виртуального DOM к реальному DOM. Этот процесс называется “согласованием” (reconciliation).

  4. Обновление реального DOM: После того как React определил необходимые изменения, он применяет их к реальному DOM, обновляя только те элементы, которые были изменены.

Преимущества виртуального DOM

  1. Уменьшение количества операций с DOM: Использование виртуального DOM позволяет уменьшить количество манипуляций с реальным DOM за счет оптимизации и минимизации обновлений, что улучшает производительность приложения.

  2. Более эффективные обновления: За счет сравнения виртуального DOM с предыдущим состоянием, React определяет только те части интерфейса, которые действительно изменились, и обновляет только их, что делает процесс обновления более эффективным.

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

  4. Улучшенный опыт разработчика: Разработчики могут сосредоточиться на логике приложения, не беспокоясь о низкоуровневых деталях манипуляций с DOM, благодаря тому, что React заботится об этом автоматически.

Однонаправленный поток данных

Принцип однонаправленного потока данных в React

Принцип однонаправленного потока данных в React означает, что данные передаются от родительских компонентов к дочерним компонентам через свойства (props). Это означает, что данные могут изменяться только в родительском компоненте, и дочерние компоненты не могут изменять данные напрямую. Если дочерний компонент хочет изменить данные, он должен вызвать функцию обратного вызова, переданную ему в качестве свойства.

Передача данных через свойства (props) и состояние компонентов

  1. Свойства (props):
    • Свойства (props) - это данные, которые передаются от родительского компонента к дочернему компоненту.
    • Свойства передаются в виде атрибутов компонентов в JSX.
    • Дочерний компонент получает свойства в качестве аргументов функции или через объект props.
  2. Состояние компонентов:
    • Состояние (state) - это внутренние данные компонента, которые могут изменяться во время работы приложения.
    • Классовые компоненты в React могут иметь состояние, которое управляется с помощью метода setState().
    • Функциональные компоненты могут использовать хуки, такие как useState, для добавления состояния.

Примеры передачи данных между компонентами

  1. При использовании свойств (props):
// Родительский компонент
function ParentComponent() {
  const data = "Hello from Parent";
  return <ChildComponent data={data} />;
}

// Дочерний компонент
function ChildComponent(props) {
  return <p>{props.data}</p>;
}
  1. При использовании состояния и функций обратного вызова:
// Родительский компонент
class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  incrementCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return <ChildComponent count={this.state.count} increment={this.incrementCount} />;
  }
}

// Дочерний компонент
function ChildComponent(props) {
  return (
    <div>
      <p>Count: {props.count}</p>
      <button onClick={props.increment}>Increment</button>
    </div>
  );
}

В обоих примерах данные передаются от родительского компонента к дочернему компоненту через свойства (props). Передача данных через состояние и функции обратного вызова происходит аналогичным образом.

Жизненный цикл компонентов

Что такое жизненный цикл компонентов в React

Жизненный цикл компонентов в React представляет собой последовательность этапов, через которые проходит компонент, начиная с его создания и заканчивая удалением из DOM. Каждый этап жизненного цикла предоставляет различные методы, которые позволяют реагировать на определенные события и выполнять соответствующие действия.

Основные методы жизненного цикла компонентов и их назначение

  1. Mounting (создание):
    • constructor(): Вызывается при создании компонента. Используется для инициализации состояния и привязки методов.
    • render(): Обязательный метод, который возвращает React-элементы, описывающие структуру компонента.
    • componentDidMount(): Вызывается сразу после того, как компонент был добавлен в DOM. Используется для выполнения загрузки данных с сервера, подписки на события или других побочных эффектов.
  2. Updating (обновление):
    • shouldComponentUpdate(): Вызывается перед рендерингом компонента. Используется для оптимизации производительности, путем предотвращения лишних обновлений.
    • render(): Обновляет представление компонента в соответствии с новыми данными.
    • componentDidUpdate(): Вызывается после обновления компонента и обновления DOM. Используется для выполнения действий, которые зависят от изменений в компоненте или DOM.
  3. Unmounting (удаление):
    • componentWillUnmount(): Вызывается перед тем, как компонент будет удален из DOM. Используется для отмены подписок, очистки ресурсов или выполнения других необходимых действий перед удалением компонента.
  4. Error Handling (обработка ошибок):
    • componentDidCatch(): Вызывается при возникновении ошибки в методах жизненного цикла или в рендеринге дочерних компонентов. Используется для обработки ошибок и предотвращения падения всего приложения.

Как использовать методы жизненного цикла

  • Загрузка данных: Используйте componentDidMount() для загрузки данных с сервера после создания компонента.
  • Оптимизация производительности: Используйте shouldComponentUpdate() для предотвращения лишних ререндеров компонента при изменении состояния или свойств.
  • Очистка ресурсов: Используйте componentWillUnmount() для отписки от событий, очистки таймеров или других ресурсов перед удалением компонента.
  • Обработка ошибок: Используйте componentDidCatch() для отлова и обработки ошибок, которые могут возникнуть в компонентах или их дочерних элементах.

Хуки React

Введение

Хуки (Hooks) - это новое API, предоставленное React с версии 16.8, которое позволяет функциональным компонентам использовать состояние и другие возможности React, которые ранее были доступны только в классовых компонентах. Хуки позволяют писать более чистый и лаконичный код, делая его более читаемым и поддерживаемым.

useState

  • Хук useState используется для добавления локального состояния в функциональные компоненты.

  • Он принимает начальное значение состояния и возвращает пару значений: текущее значение состояния и функцию для его обновления.

  • Пример:

    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
      );
    }

useEffect

  • Хук useEffect позволяет выполнить побочные эффекты в функциональных компонентах.

  • Он принимает функцию-эффект и опциональный массив зависимостей и запускает этот эффект после каждого рендера компонента.

  • Пример:

    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        document.title = `You clicked ${count} times`;
      }, [count]);
    
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
      );
    }

useContext

  • Хук useContext используется для получения значения контекста React.

  • Он принимает объект контекста, возвращаемый функцией React.createContext(), и возвращает текущее значение контекста.

  • Пример:

    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light');
    
    function ThemedComponent() {
      const theme = useContext(ThemeContext);
      return <p>Current theme: {theme}</p>;
    }
    
    function App() {
      return (
        <ThemeContext.Provider value="dark">
          <ThemedComponent />
        </ThemeContext.Provider>
      );
    }

useMemo

Хук useMemo в React используется для мемоизации результатов выполнения функции, чтобы избежать избыточных вычислений во время рендеринга компонентов. Он принимает функцию и массив зависимостей, и возвращает кешированное значение функции.

Назначение хука useMemo:

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

Синтаксис:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • computeExpensiveValue - функция, результат выполнения которой мы хотим мемоизировать.
  • [a, b] - массив зависимостей. Если хотя бы одно значение из этого массива изменится, useMemo вызовет функцию computeExpensiveValue снова.

Пример использования хука useMemo:

Рассмотрим пример, где у нас есть компонент, который отображает сумму элементов массива. Если массив или его элементы не изменились, мы можем использовать useMemo, чтобы избежать повторного вычисления суммы каждый раз при рендеринге.

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

function ArraySum({ array }) {
  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return array.reduce((acc, curr) => acc + curr, 0);
  }, [array]);

  return <div>Sum: {sum}</div>;
}

function App() {
  const [array, setArray] = useState([1, 2, 3, 4, 5]);

  const updateArray = () => {
    setArray(prevArray => [...prevArray, prevArray.length + 1]);
  };

  return (
    <div>
      <ArraySum array={array} />
      <button onClick={updateArray}>Add Element</button>
    </div>
  );
}

export default App;

В этом примере useMemo используется для вычисления суммы элементов массива только в случае изменения самого массива. Каждый раз, когда мы добавляем новый элемент в массив, рендерится компонент ArraySum, но вычисление суммы не происходит заново, если массив не изменился. Это позволяет избежать ненужных вычислений и повышает производительность приложения.

useReducer

Хук useReducer в React предоставляет альтернативный способ управления состоянием компонентов по сравнению с useState. Он предлагает более мощный способ управления состоянием, особенно для более сложных состояний, которые могут быть связаны с различными действиями. useReducer основан на принципе Redux и позволяет управлять состоянием компонента с помощью функции редуктора.

Назначение хука useReducer:

Хук useReducer предназначен для управления состоянием компонента, где состояние представляет собой объект с данными, а изменения состояния происходят через действия (actions). Редуктор (reducer) - это функция, которая принимает предыдущее состояние и действие, и возвращает новое состояние. useReducer позволяет компоненту обрабатывать сложные логические операции и управлять состоянием более явно.

Синтаксис:

const [state, dispatch] = useReducer(reducer, initialState);
  • reducer - функция, которая принимает текущее состояние и действие, и возвращает новое состояние.
  • initialState - начальное значение состояния.

Пример использования хука useReducer:

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

import React, { useReducer } from 'react';

// Редуктор для управления состоянием счетчика
const counterReducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

function Counter() {
  // Использование useReducer для управления состоянием
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
    </div>
  );
}

export default Counter;

В этом примере мы определили редуктор counterReducer, который обрабатывает действия 'INCREMENT' и 'DECREMENT', изменяя состояние счетчика соответственно. Затем мы используем useReducer, чтобы управлять состоянием счетчика в компоненте Counter. Каждый раз, когда пользователь нажимает кнопки “Increment” или “Decrement”, мы диспетчеризуем соответствующее действие, которое передается редуктору, и состояние обновляется соответственно. Это позволяет нам управлять состоянием компонента более явно и четко определять логику обработки действий.

useCallback

Хук useCallback в React используется для мемоизации колбэк-функций, чтобы предотвратить их повторное создание при каждом рендере компонента. Это позволяет оптимизировать производительность компонентов, особенно в случаях, когда колбэк-функции передаются как пропсы дочерним компонентам и могут вызываться заново при каждом рендере.

Назначение хука useCallback:

Когда функциональный компонент рендерится, функции, определенные внутри его функции, пересоздаются при каждом вызове рендера. Это может привести к избыточным ререндерам дочерних компонентов, которым передаются эти функции в качестве пропсов. useCallback позволяет сохранить эти колбэк-функции между рендерами, чтобы они не пересоздавались каждый раз.

Синтаксис:

const memoizedCallback = useCallback(() => {
  // колбэк-логика
}, [dependencies]);
  • callback - функция, которую мы хотим мемоизировать.
  • dependencies - массив зависимостей. Если хотя бы одно значение из этого массива изменится, useCallback создаст новую функцию.

Пример использования хука useCallback:

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

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

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

  // Мемоизированная колбэк-функция с помощью useCallback
  const handleClick = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent onClick={handleClick} />
    </div>
  );
}

function ChildComponent({ onClick }) {
  return <button onClick={onClick}>Increment</button>;
}

export default ParentComponent;

В этом примере мы используем useCallback, чтобы мемоизировать колбэк-функцию handleClick, которая увеличивает счетчик при каждом вызове. Поскольку зависимостей нет ([]), эта функция будет создана только один раз при первом рендере ParentComponent, а затем будет использоваться при последующих рендерах без повторного создания. Это позволяет оптимизировать производительность компонента, предотвращая ненужные ререндеры.

useRef

Хук useRef в React используется для создания изменяемого объекта, который будет сохраняться между рендерами компонента. Основное назначение useRef - это получение ссылки на DOM-элемент или другой объект в функциональном компоненте.

Назначение хука useRef:

  1. Ссылка на DOM-элементы: useRef позволяет получить ссылку на DOM-элемент, чтобы иметь возможность взаимодействовать с ним напрямую из функционального компонента.

  2. Сохранение значения между рендерами: useRef также может использоваться для сохранения значений между рендерами компонента без вызова повторного рендера. Значение, сохраненное в объекте ref, будет сохраняться между рендерами и изменениями состояния без вызова эффектов повторного рендера.

Синтаксис:

const refContainer = useRef(initialValue);
  • initialValue - необязательный параметр, который устанавливает начальное значение ссылки. Это может быть любое значение, включая DOM-элемент или объект.

Пример использования хука useRef:

  1. Ссылка на DOM-элемент:
import React, { useRef } from 'react';

function TextInputWithFocusButton() {
  const inputRef = useRef(null);

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}

В этом примере мы используем useRef, чтобы получить ссылку на <input> элемент и сделать его активным при нажатии на кнопку.

  1. Сохранение значения между рендерами:
import React, { useState, useRef } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef();

  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };

  return (
    <div>
      <p>Timer: {seconds} seconds</p>
      <button onClick={startTimer}>Start Timer</button>
      <button onClick={stopTimer}>Stop Timer</button>
    </div>
  );
}

В этом примере мы используем useRef, чтобы сохранить ссылку на интервал таймера между рендерами. Это позволяет нам запускать и останавливать таймер, сохраняя при этом состояние компонента без вызова повторного рендера.