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

Полное руководство по перехватчикам React: Упрощение состояния и побочных эффектов

В самом начале мы разберемся в React Hooks:

Перехватчики React произвели революцию в том, как мы пишем компоненты React, предоставив более простой и элегантный подход к управлению состоянием и обработке побочных эффектов. В этой статье мы рассмотрим основные хуки в React и углубимся в пользовательские хуки, расширенные шаблоны хуков и лучшие практики. Давайте начнем!

Преимущества использования перехватчиков по сравнению с компонентами класса

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

Понимание основных перехватчиков:

1. Перехватчик useState

Хук 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>
  );
}

В приведенном выше коде мы инициализируем состояние счетчика равным 0, используя useState. Отображается значение счетчика, и функция setCount используется для обновления счетчика при нажатии кнопки.

2. Перехватчик useEffect

Хук useEffect позволяет нам выполнять побочные эффекты в функциональных компонентах, например извлекать данные из API, подписываться на события или манипулировать DOM. Он принимает функцию обратного вызова и необязательный массив зависимостей для управления запуском эффекта. Давайте посмотрим на пример получения данных из API с помощью useEffect:

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

function DataFetcher() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      {data.map(item => (
        <p key={item.id}>{item.name}</p>
      ))}
    </div>
  );
}

В этом коде мы используем useEffect для извлечения данных из API при подключении компонента. Извлеченные данные сохраняются в состоянии с помощью функции setData и отображаются в компоненте.

3. Перехватчик useContext

Хук useContext предоставляет способ доступа к общему состоянию или данным без углубления в детали. Это позволяет нам создавать контекст и использовать его в любом компоненте поставщика контекста. Давайте посмотрим на пример создания компонента переключения тем с помощью useContext:

import React, { useContext } from 'react';

const ThemeContext = React.createContext('light');

function ThemeSwitcher() {
  const theme = useContext(ThemeContext);

  return (
    <div>
      <p>Current theme: {theme}</p>
      <button onClick={() => console.log('Switch theme')}>Switch Theme</button>
    </div>
  );
}

В приведенном выше коде мы создаем ThemeContext с помощью React.createContext и предоставляем значение по умолчанию 'light'. Хук useContext используется в компоненте ThemeSwitcher для доступа к текущему значению темы. Когда кнопка нажата, она запускает действие переключения темы.

Пользовательские хуки: повторное использование и абстракция:

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

Создание хука проверки формы:

Давайте создадим собственный хук для проверки формы. Хук будет обрабатывать логику проверки и возвращать состояние проверки и функции для обновления значений формы и запуска проверки.

Перехватчик useFormValidation

import React, { useState } from 'react';

function useFormValidation(initialState, validate) {
  const [values, setValues] = useState(initialState);
  const [errors, setErrors] = useState({});
  const [isSubmitting, setSubmitting] = useState(false);

  const handleChange = event => {
    setValues({
      ...values,
      [event.target.name]: event.target.value
    });
  };

  const handleSubmit = event => {
    event.preventDefault();
    setErrors(validate(values));
    setSubmitting(true);
  };

  return { values, errors, isSubmitting, handleChange, handleSubmit };
}

Объяснение:

Пользовательский хук useFormValidation обрабатывает состояние и логику проверки формы. Он принимает initialState — объект, представляющий начальные значения формы, и validate — функцию проверки значений формы. Он возвращает объект со values, errors, isSubmitting, handleChange и handleSubmit.

  1. values: представляет текущие значения формы.
  2. errors: содержит все ошибки проверки формы.
  3. isSubmitting: указывает, отправляется ли форма.
  4. handleChange: это функция, которая обновляет значения формы по мере ввода пользователем.
  5. handleSubmit: это функция, которая обрабатывает отправку формы, запускает проверку и устанавливает ошибки и состояние отправки.

Компонент LoginForm


function validateLoginForm(values) {
  let errors = {};

    if (!values.email) {
    errors.email = 'Email is required';
  }

    if (!values.password) {
    errors.password = 'Password is required';
  } else if (values.password.length < 6) {
    errors.password = 'Password must be at least 6 characters long';
  }

  return errors;
}

function LoginForm() {
  const { values, errors, isSubmitting, handleChange, handleSubmit } = useFormValidation(
    { email: '', password: '' },
    validateLoginForm
  );

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="email">Email</label>
        <input
          type="email"
          id="email"
          name="email"
          value={values.email}
          onChange={handleChange}
        />
        {errors.email && <span>{errors.email}</span>}
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input
          type="password"
          id="password"
          name="password"
          value={values.password}
          onChange={handleChange}
        />
        {errors.password && <span>{errors.password}</span>}
      </div>
      <button type="submit" disabled={isSubmitting}>
        Submit
      </button>
    </form>
  );
}

export default LoginForm;

Объяснение:

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

Внутри компонента мы деструктурируем values, errors, isSubmitting, handleChange и handleSubmit из хука useFormValidation. Эти значения и функции затем используются в JSX для отображения формы.

Усовершенствованные шаблоны хуков:

1. Хук useReducer

Хук useReducer — это альтернатива useState при управлении более сложным состоянием, включающим несколько действий. Он следует шаблону Redux для управления состоянием с помощью редюсеров и действий. Давайте посмотрим на пример реализации списка задач с помощью useReducer:

import React, { useReducer } from 'react';

function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, { id: Date.now(), text: action.payload, completed: false }];
    case 'TOGGLE_TODO':
      return state.map(todo => (todo.id === action.payload ? { ...todo, completed: !todo.completed } : todo));
    case 'REMOVE_TODO':
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
}

function TodoList() {
  const [todos, dispatch] = useReducer(todoReducer, []);

  const handleAddTodo = () => {
    const todoText = // Get todo text from input field
    dispatch({ type: 'ADD_TODO', payload: todoText });
  };

  return (
    <div>
      <input type="text" placeholder="Enter todo" />
      <button onClick={handleAddTodo}>Add Todo</button>

      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <span>{todo.text}</span>
            <button onClick={() => dispatch({ type: 'TOGGLE_TODO', payload: todo.id })}>
              {todo.completed ? 'Mark Incomplete' : 'Mark Complete'}
            </button>
            <button onClick={() => dispatch({ type: 'REMOVE_TODO', payload: todo.id })}>Remove</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

В этом примере у нас есть функция todoReducer, которая принимает текущее состояние и действие и в зависимости от типа действия выполняет необходимые обновления состояния. Функция редуктора обрабатывает три типа действий: добавление новой задачи, переключение состояния завершения задачи и удаление задачи.

Компонент TodoList использует хук useReducer, вызывая его с помощью функции todoReducer и начального состояния пустого массива []. Хук возвращает текущее состояние (todos) и функцию dispatch, которую мы используем для отправки действий редюсеру.

Функция handleAddTodo вызывается при нажатии кнопки "Add Todo". Он извлекает текст задачи из поля ввода (которое не включено в этот фрагмент кода) и отправляет действие типа 'ADD_TODO' с полезной нагрузкой в качестве текста задачи. Затем функция редуктора добавляет новый объект задачи в массив состояний, включая автоматически сгенерированный идентификатор, текст задачи и статус завершения по умолчанию false.

Компонент TodoList отображает поле ввода и кнопку для добавления новых задач. Ниже он отображает список задач с помощью функции todos.map. Каждая задача отображается как элемент <li> с отображаемым текстом. Кроме того, для каждой задачи есть две кнопки: одна для переключения статуса завершения и другая для удаления задачи. Когда эти кнопки нажаты, соответствующие действия отправляются редьюсеру для соответствующего обновления состояния.

2. Хук useRef

Доступ и сохранение значений между рендерами:

Хук useRef позволяет сохранять значения между рендерингами, не запуская повторный рендеринг. Его также можно использовать для прямого доступа к элементам DOM. Давайте посмотрим на пример реализации поля ввода с помощью useRef:

import React, { useRef } from 'react';

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

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

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

В этом коде inputRef создается с использованием useRef и назначается атрибуту ref элемента ввода. Когда кнопка нажата, запускается функция handleClick, которая фокусирует элемент ввода, используя текущее свойство ref.

Вывод

React Hooks изменили то, как мы пишем компоненты React, предлагая более рациональный и функциональный подход к управлению состоянием и обработке побочных эффектов. Используя основные хуки, такие как useState, useEffect и useContext, мы можем упростить наш код и улучшить возможность повторного использования. Кроме того, настраиваемые хуки и расширенные шаблоны хуков, такие как useReducer и useRef, предоставляют мощные инструменты для создания сложных и оптимизированных компонентов.

Когда вы отправляетесь в путешествие по React, я призываю вас исследовать и экспериментировать с React Hooks в своих проектах. Их гибкость, простота и преимущества в производительности, несомненно, улучшат ваш опыт разработки. Удачного кодирования!

Источник:

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

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

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

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