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

В этом руководстве вы узнаете, как точно использовать хуки в React. Мы создадим простой веб-сайт, который предоставит пользователю несколько вариантов выбора, чтобы сгенерировать случайные числа.

Вы можете посмотреть демонстрацию для веб-сайта здесь, а исходный код - в репозитории GitHub.

Начнем с создания приложения для реагирования. Поскольку наш сайт будет очень простым, мы будем использовать команду create-react-app. Если он у вас не установлен, вы можете установить его с помощью npm .

Запустите в терминале или CMD следующее:

npm i -g create-react-app

Это установит create-react-app глобально.

Теперь мы можем создать наше приложение React:

create-react-app numbers-trivia

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

Внутри этого каталога он также установит все пакеты и файлы, необходимые для запуска веб-сайта. Он установит такие пакеты, как react, react-dom, response-scripts и другие.

Как только это будет сделано, перейдите во вновь созданный каталог и запустите сервер:

cd numbers-trivia
npm start

После запуска сервера откроется веб-страница вашего веб-сайта в вашем любимом браузере. Вы увидите страницу с логотипом и ссылкой для изучения React.

Прежде чем мы начнем менять страницу, если вы не знакомы с React, давайте взглянем на структуру нашего приложения React. Это должно выглядеть примерно так:

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

Каталог, в котором мы будем проводить большую часть времени, - это каталог src. Этот каталог будет содержать все наши компоненты React.

Как видите, в этом каталоге есть куча файлов. index.js - это, по сути, файл, который отображает самый высокий компонент React.

Прямо сейчас у нас есть только один компонент React, который находится в App.js. Если вы откроете его, вы найдете код, который отображает логотип со ссылкой для изучения React, которую вы сейчас видите на веб-сайте.

Итак, чтобы увидеть, как изменение нашего компонента приложения повлияет на содержимое веб-сайта, давайте изменим код, удалив текущий контент и заменив его нашей любимой фразой: «Hello, World!»

import React, { Component } from 'react' 
import logo from './logo.svg' 
import './App.css'  
class App extends Component {
   render() {
     return (
       <div className="App">
         <header className="App-header">
           <h1>Hello, World!</h1>
         </header>
       </div>
     )
   }
 }
export default App

Мы просто заменили содержимое элемента header. Теперь, если ваш сервер все еще работает, вы увидите, что ваша страница обновилась без обновления, и вы увидите, что предыдущее содержимое заменено на Hello, World!

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

Что мы сделаем для этого веб-сайта:

  1. Показывать приветственное сообщение при первом открытии веб-сайта пользователем, а затем заменять его сообщением, предлагающим пользователю попробовать генератор.
  2. Визуализируйте форму с полями текст и выбор. Поле ввода текст - это то место, где пользователь может ввести число, о котором он хочет видеть мелочи, а ввод выбрать предоставит пользователю параметры, связанные с мелочами.
  3. При отправке формы отправьте запрос в этот API, чтобы получить нужные нам мелочи.
  4. Визуализируйте мелочи, чтобы пользователь мог их увидеть.

Давайте начнем с организации нашей структуры каталогов. В React рекомендуется создавать каталог внутри src, содержащий все компоненты. Мы создадим каталог под названием компоненты. Создав каталог, переместите туда App.js. Мы также создадим каталог под названием стили и переместим в него App.css и index.css.

Когда вы это сделаете, вам нужно будет изменить импорт в ваших файлах следующим образом:

  1. в index.js:
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import '../styles/index.css'; 
import App from './components/App'; 
import  as serviceWorker from './serviceWorker';

2. в App.js:

import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import '../styles/App.css';

Наша структура каталогов теперь должна выглядеть так:

Сейчас мы продолжим и начнем создавать нашу веб-страницу.

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

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

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

useEffect(() => {
  //perform something post render
});

Функция, которую вы передаете useEffect, будет выполняться после каждого рендеринга. Это объединяет методы жизненного цикла componentDidMount и componentDidUpdate в один.

Что, если вы хотите что-то сделать сразу после первого рендеринга компонента, как в componentDidMount? Вы можете сделать это, передав второй параметр useEffect.

useEffect принимает массив в качестве второго параметра. Этот параметр используется как условие того, когда следует выполнять переданную функцию. Итак, допустим, вы хотите изменить счетчик только после изменения переменной counter, вы можете сделать это так:

useEffect(() => document.title = `You have clicked ${counter} times`, [counter]);

Таким образом, функция, переданная в useEffect, будет выполняться после рендеринга, только если значение counter изменится.

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

Давайте теперь вернемся к тому, чем мы хотим заниматься. Мы хотим показать приветственное сообщение, когда пользователь впервые открывает страницу, а затем изменить это сообщение через 3 секунды. Мы можем сделать это, добавив в App.js следующее:

import React, {useEffect} from 'react'; 
import Form from './Form'; 
import '../styles/App.css'; 
 
function App() {
   useEffect(() => {
     setTimeout(() => {
       let welcomeMessage = document.getElementById("welcomeMessage");
       welcomeMessage.innerHTML = "Try Out Our Trivia Generator!";
     }, 3000);
   }, []);
   return (
     <div className="App">
       <header className="App-header">
         <h1 id="welcomeMessage">Welcome to Numbers Trivia!</h1>
         <Form />
       </header>
     </div>
   ); }  
export default App;

Вот что мы делаем:

  1. Строка 1: Мы добавили импорт для useEffect
  2. Строка 4: Мы превратили наш компонент класса в функциональный компонент.
  3. Строка 5–10: мы добавили эффект к нашему функциональному компоненту. Этот эффект устанавливает таймер через 3 секунды, который изменит текст в элементе с идентификатором welcomeMessage . Поскольку мы передали в useEffect пустой массив, этот эффект сработает только один раз.
  4. Строка 11–17. Мы заменили предыдущий код в App.js, чтобы отобразить элемент h1 с идентификатором welcomeMessage , , который является нашим целевым элементом.

Хорошо, теперь перейдите на нашу веб-страницу и посмотрите изменения. Сначала появится приветственное сообщение «Добро пожаловать в Numbers Trivia!», а затем через 3 секунды оно изменится на «Попробуйте наш генератор викторины!». Мы только что использовали React Hook!

Затем давайте создадим элементы ввода нашей формы. Для этого мы создадим новый компонент React с именем Form . Создайте в каталоге компоненты файл Form.js. На данный момент он будет включать только следующее:

import React from 'react';  
function Form(props){
}
export default Form;

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

В форме у нас будет поле ввода текст и элементы select. Это основано на API, который мы используем. В API можно отправить два параметра:

  1. номер: номер, для которого вы хотите получить викторину. Это может быть целое число, дата в форме месяц / день или ключевое слово случайное, с помощью которого извлекаются факты о случайном числе.
  2. type: тип информации, которую вы хотите получить. Есть несколько типов: математические, дата, год или, по умолчанию, мелочи.

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

Давайте добавим следующий код в функцию Form, чтобы отобразить нашу форму:

function Form(props){
  return (<form>
             <div>
              <input type="text" name="number" placeholder="Enter a number (Optional)" />
             </div>
             <div>
              <select name="type">
               <option value="trivia">Trivia</option>
               <option value="math">Math</option>
               <option value="date">Date</option>
               <option value="year">Year</option>
              </select>
             </div>
             <button type="submit">Generate</button>
            </form>); 
}

Будет создана форма с вводом текст и элементами select и button.

После этого нам нужно импортировать и отобразить компонент Форма в нашем компоненте Приложение:

import React, {useEffect} from 'react';
import Form from './Form';
import '../styles/App.css';  
function App() {
   useEffect(() => {
     setTimeout(() => {
       let welcomeMessage = document.getElementById("welcomeMessage");
       welcomeMessage.innerHTML = "Try Out Our Trivia Generator!";
     }, 3000);
   }, []);
   return (
     <div className="App">
       <header className="App-header">
         <h1 id="welcomeMessage">Welcome to Numbers Trivia!</h1>
         <Form />
       </header>
     </div>
   );
 }
export default App;

Мы изменили импорт для импорта нашего Form компонента и добавили <Form /> для визуализации формы.

Давайте также добавим больше стилей, чтобы наша форма выглядела немного лучше. Добавьте в конец App.css следующее:

form {
   font-size: 15px;
}  
form input, form select {
   padding: 5px;
}  
form select {
   width: 100%; 
}  
form div {
   margin-bottom: 8px;
}

Если вы обновите страницу сейчас, вы обнаружите, что она изменилась и теперь показывает нашу форму.

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

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

Перед перехватами, чтобы получить значение в состоянии, вам нужно будет использовать this.state.value ,, а затем, чтобы установить состояние, вам нужно будет вызвать this.setState.

Теперь вы можете использовать ловушку состояния. Хук состояния - это useState функция. Он принимает один аргумент, который является начальным значением, и возвращает пару значений: текущее состояние и функция, которая его обновляет. Затем вы сможете получить доступ к текущему состоянию, используя первое возвращаемое значение, и обновить его, используя второе возвращаемое значение, которое является функцией.

Вот пример:

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

в этом примере мы вызываем ловушку useState и передаем ему 0, а возвращаемое значение устанавливаем равным count и setCount. Это означает, что мы создали переменную состояния с именем count. Его начальное значение равно 0, и для изменения его значения мы можем использовать setCount.

Для нашего Form компонента нам нужны две переменные состояния: одна для ввода текста , который мы будем называть number, и одна для ввода выбора , который мы позвоним type. Затем, при событии изменения для этих двух входных элементов, мы изменим значения для number и type, используя функцию, возвращаемую setState .

Откройте наш Form компонент и измените его на следующее:

import React, { useState } from 'react';
function Form(props){
  let [number, setNumber] = useState("random");
  let [type, setType] = useState("trivia");
  function onNumberChanged(e){
    let value = e.target.value.trim();
    if(!value.length){
      setNumber("random"); //default value
    } else {
      setNumber(value);
    }
  }
  function onTypeChanged(e){
    let value = e.target.value.trim();
    if(!value.length){
      setType("trivia"); //default value
    } else {
      setType(value);
    }
  }
  return (<form>
            <div>
              <input type="text" name="number" placeholder="Enter a number (Optional)" value={number} onChange={onNumberChanged} />
            </div>
            <div>
              <select name="type" value={type} onChange={onTypeChanged}>
                <option value="trivia">Trivia</option>
                <option value="math">Math</option>
                <option value="date">Date</option>
                <option value="year">Year</option>
              </select>
            </div>
            <button type="submit">Generate</button>
</form>);
}
export default Form;
  1. Строка 1: добавьте импорт для ловушки useState.
  2. Строка 3–4: создайте две переменные состояния number и type с помощью useState. Здесь мы передаем random как начальное значение для number и trivia как начальное значение для type, потому что они являются значениями по умолчанию для параметров в API.
  3. Строка 5–10: реализуем функции обработчика изменения ввода как для текста, так и для ввода выбора, где мы изменяем значение переменных состояния с помощью функций, возвращаемых useState. Если значение не установлено, мы автоматически меняем значения на значение по умолчанию.
  4. Строка 13: передайте функцию onNumberChanged событию onChange для ввода текста.
  5. Строка 16: передайте функцию onTypeChanged событию onChange для выбора ввода.

Кроме того, давайте вернемся к нашему App компоненту, чтобы изменить его и использовать состояния. Вместо того, чтобы изменять приветственное сообщение, изменяя innerHTML элемента, мы будем использовать состояние. Теперь наш компонент приложения должен выглядеть так:

import React, {useEffect, useState} from 'react'; 
import Form from './Form'; 
import '../styles/App.css'; 
 
function App() {
  const [ welcomeMessage, setWelcomeMessage ] = useState(
    "Welcome to Numbers Trivia!",
  );
useEffect(() => {
    setTimeout(() => {
      setWelcomeMessage("Try Out Our Trivia Generator!");
    }, 3000);
  }, []);
return (
    <div className="App">
      <header className="App-header">
        <h1>{welcomeMessage}</h1>
      </header>
      <Form/>
    </div>
  );
}
export default App;

Теперь мы используем useState для объявления и инициализации нашего приветственного сообщения. Он вернет welcomeMessage, нашу переменную состояния, и setWelcomeMessage, которые мы будем использовать для изменения значения welcomeMessage через 3 секунды с «Добро пожаловать в Numbers Trivia!» на «Попробуйте наш генератор викторины» ! »

Теперь осталось добавить функцию для обработки события onSubmit формы. При отправке мы отправим запрос в API с нашими параметрами, а затем отобразим результат.

Для выполнения запроса нам необходимо установить axios:

npm i axios

Затем потребуйте аксиом в начале Form.js:

const axios = require('axios');

Теперь добавьте следующую функцию под onTypeChanged в наш компонент Форма:

function onSubmit(e){
  e.preventDefault();
  axios.get('http://numbersapi.com/' + number + '/' + type)
       .then(function(response){
         let elm = document.getElementById('result');
         elm.innerHTML = response.data;
       }).catch(function(e){
         console.log("error", e); //simple error handling
       });
}

Мы просто выполняем запрос к API, передаем number и type, а затем отображаем результат в элементе с идентификатором result (который мы добавим через минуту). В случае ошибки мы просто отображаем ее в консоли как простую процедуру обработки ошибок.

Теперь давайте добавим эту функцию в качестве обработчика для события form onSubmit в операторе return в Form.js:

<form onSubmit={onSubmit}>

Осталось только добавить элемент #result. Мы можем добавить его в App.js до <Form />:

<div id="result" style={{marginBottom: '15px'}}></div>

Хорошо, теперь зайдите на свой сайт и узнайте все новые мелочи о числах!

Заключение

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