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

Начнем с основных вещей, связанных с React:

Вавилон:

Babel — это транспилятор, который преобразует ваш (JSX в JS) современный код JavaScript в более старую версию, а затем добавляет полифиллы, фрагмент кода, который реализует функции, отсутствующие в браузере, но необходимые вашему приложению.

Вы можете настроить свою собственную конфигурацию babel с помощью Webpack, как я показываю в этой статье. Или вы можете использовать create-react-app, который внутренне использует Babel для преобразования JSX в JavaScript.

Вебпак

Webpack — это сборщик модулей для JavaScript, который объединяет все необходимое для вашего приложения. Эта библиотека также может выполнять такие задачи, как запуск Babel, Jest, ESLint и PostCSS поверх вашего кода.

undefined, null и boolean не отображаются в пользовательском интерфейсе при использовании внутри JSX.

Что делают реагирующие скрипты

Сценарии реакции — это просто сценарии для запуска инструментов сборки, необходимых для программного преобразования синтаксиса React JSX в простой JavaScript. Файл package.json реагирующего скрипта содержит все зависимости, такие как Babel и webpack.

Этот пакет содержит четыре сценария:

"scripts: {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "eject": "react-scripts eject"
},

Когда вы запускаете один из скриптов, для запуска процесса будет выполнен файл /bin/react-scripts.js. Этот скрипт проверит аргументы, которые вы передали в вызов. Он принимает только аргументы запуска, сборки, тестирования и извлечения.

Рендеринг на стороне сервера:

Рендеринг на стороне сервера — это метод или метод, при котором HTML строится на сервере и отправляет HTML с сервера клиенту. это позволяет пользователю просматривать некоторый пользовательский интерфейс во время загрузки пакета JS и до того, как приложение станет интерактивным.

  • Браузер запрашивает страницу
  • Контент, видимый пользователю (поскольку HTML создается на сервере)
  • Браузер запрашивает связанный пакет JS
  • Реагировать на загрузку приложения
  • Пользователи могут взаимодействовать с приложением
  • Запрос данных API
  • Повторно визуализировать приложение React с новыми данными

Визуализация на стороне клиента:

CSR (рендеринг на стороне клиента) происходит, когда пустой файл HTML сначала загружается в браузер, а затем HTML создается в браузере и запускается рисование.

  • Браузер запрашивает страницу
  • Пустой index.html загружен
  • Браузер запрашивает связанный пакет JS
  • Реагировать на загрузку приложений
  • Контент, видимый пользователю (поскольку HTML встроен в браузер)
  • Пользователи могут взаимодействовать с приложением
  • Запрос данных API
  • Повторно визуализировать приложение React с новыми данными

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

ССР против КСО:

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

40 баллов от ReactJS:

1. Создайте приложение React

// Initialize a new app
npx create-react-app app_Name
OR
yarn create-react-app app_Name 
cd app_Name
// Run the app (default port is 3000)
npm start
OR
yarn start

2. Рендеринг React-компонента

Старый метод:

import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
   return <div>Render Me!</div>
}
ReactDOM.render(<App />, document.getElementById('root'));

Новый метод:

import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(
    document.getElementById("root")
);
root.render( <App/> );

3. Функциональные компоненты

Правило:

  1. Должен иметь первую букву в верхнем регистре
  2. Должен возвращать JSX
const TestComponent = () => {
    return <div> Hello World </div>;
};
export default TestComponent;

4. Компоненты класса

До функции класса ES6:

const SecondComponent = React.createClass({
 render: function() {
  return( < div > {
   this.props.content
  } < /div>);
 }
});

С ключевым словом класса ES6:

class TestComponent extends React.Component {
    render() {
        return <h1> Hello, JavaScriptCentric! </h1>;
    }
}
export default TestComponent;

Правила крючков:

а) Не вызывайте хуки внутри циклов, условий или вложенных функций.

б) Не вызывайте хуки из обычной функции Javascript.

c) Хуки должны вызываться на верхнем уровне нашего компонента.

г) Пользовательские хуки начинаются с use___

5. Используйте Крюк Эффекта:

a) С пустым массивом. Он работает как componentDidMount, а побочный эффект запускается один раз после первоначального рендеринга.

useEffect(() => {
console.log('only once at componentDidMount!');
}, []);

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

useEffect(() => {
console.log('Every time when value of yourDependency changes');
}, [yourDependency]);

c) С оператором return (функция очистки от побочных эффектов) он работает как componentWillUnmount, а побочный эффект запускается, когда компонент размонтирован. (после размонтирования компонента useEffect() вызывает функцию очистки от последнего побочного эффекта)

useEffect(() => {
// Any Side-effect or event listener
return () => {
// Clear the side-effect or any event listeners
}
}, [yourDependency]);

d) Без массива зависимостей и с оператором обновления состояния внутри него. Он работает как бесконечный цикл.

useEffect(() => setCount(count + 1));
//After initial rendering, useEffect() executes the side-effect //callback that updates the state. The state update triggers re- //rendering. After re-rendering useEffect() executes the side-effect //callback and again updates the state, which triggers again a re-  //rendering. ...and so on indefinitely.
// To Break the Infinite loop just Remove any state update statements // or Add dependency array
useEffect(() => {});  // Removed set update from useEffect
useEffect(() => {}, []);  // Added empty dependecy array

6. Реагировать на полифиллы:

Чтобы узнать, какую версию babel использует ваш create-react-app, откройте файл node_modules/react-scripts/package.json в папке вашего проекта и проверьте версию @babel/core в разделе dependencies.

npm install @babel/polyfill@latest
npm install core-js

И как только пакет core-js будет установлен, добавьте для него импорт перед всеми другими операторами импорта в вашем основном файле app.js или index.js как

import "core-js/stable";
import "@babel/polyfill";

7. Граница ошибки в React

Границы ошибок работают как блок JavaScript catch {}, но для компонентов. Только компоненты класса могут быть границами ошибок.

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

Граница ошибки не может обнаружить ошибку внутри себя.

Компонент класса становится границей ошибки, если он определяет один (или оба) из методов жизненного цикла static getDerivedStateFromError() или componentDidCatch(). Используйте static getDerivedStateFromError() для отображения резервного пользовательского интерфейса после возникновения ошибки. Используйте componentDidCatch() для регистрации информации об ошибке.

class ErrorBoundary extends React.Component {
 
constructor(props) {
  super(props);
  this.state = {
   hasError: false
  };
 }
 static getDerivedStateFromError(error) {
  // Update state so the next render will show the fallback UI.
  return {
   hasError: true
  };
 }
 componentDidCatch(error, errorInfo) {
  // You can also log the error to an error reporting service
  logErrorToMyService(error, errorInfo);
 }
 render() {
  if(this.state.hasError) {
   // You can render any custom fallback UI
   return <h1 > Something went wrong. < /h1>;
  }
  return this.props.children;
 }
}

Затем вы можете использовать его как обычный компонент:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

8. Состав

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

Например, подумайте об использовании map() для создания нового массива из исходного набора, а затем отфильтруйте результат с помощью filter():

const list = ['Apple', 'Orange', 'Egg']
list.map(item => item[0]).filter(item => item === 'A') //'A'

9. Обработка CORS в React

Совместное использование ресурсов между источниками (CORS) относится к методу, который позволяет вам делать запросы к серверу, развернутому в другом домене. Для справки: если интерфейс и серверная часть находятся в двух разных доменах, нам нужен CORS там.

  • В Axios:Axios всегда использует базовый URL-адрес для запуска запроса, и браузер сам подтверждает это в начале запроса HTTP OPTIONS. Много раз нам нужно передавать токены для аутентификации, и токен, который мы используем, идентифицируется Bearer. Теперь в основной части нам нужно передать некоторые дополнительные заголовки для CORS с именем Access-Control-Allow-Credentials. Это требуется, потому что браузеру необходимо подтвердить, что серверу разрешен доступ к ресурсам.
  • При выборке.Чтобы использовать CORS при выборке, нам нужно использовать параметр режима и установить для него значение cors.
const makeAPICall = async () => {
    try {
        const response = await fetch('http://localhost:8080/', {
            mode: 'cors'
        });
        const data = await response.json();
        console.log({
            data
        })
    } catch (e) {
        console.log(e)
    }
}
useEffect(() => {
    makeAPICall();
}, [])

Мы можем вручную установить заголовок для cors:

componentDidMount() {
    fetch('http://localhost:8080/', {
            method: "GET",
            headers: {
                "access-control-allow-origin": "*",
                "Content-type": "application/json; charset=UTF-8"
            }
        })
        .then(results => results.json())
        .then(info => {
            console.log("Response: "info);
        });
}

10. Синтетическое событие:

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

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

11. Компоненты высшего порядка

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

Компонент высшего порядка в React — это шаблон, вытекающий из природы React, которая отдает предпочтение композиции, а не наследованию.

import React from 'react'
const higherOrderComponent = (WrappedComponent) => {
    class HOC extends React.Component {
        render() {
            return <WrappedComponent / >
        }
    }
    return HOC;
}

В приведенном выше примере более высокий ОрдерКомпонент — это функция, которая принимает компонент с именем WrappedComponent в качестве аргумента. Мы создали новый компонент под названием HOC, который возвращает ‹WrappedComponent/› из своей функции рендеринга. Хотя это на самом деле не добавляет функциональности, оно изображает общий шаблон, которому будет следовать каждая функция HOC.

Мы можем вызвать HOC следующим образом:

const SimpleHOC = higherOrderComponent(MyComponent);

Компонент более высокого порядка преобразует компонент в другой компонент. Обратите внимание, что HOC не изменяет компонент ввода. Скорее, HOC составляет исходный компонент, заключая его в компонент-контейнер.

Пример функции более высокого порядка устранения дребезга:

const fetchData = (e) => {
  console.log(e)
}
const debounce = (func, timeout=500) => {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(()=>{
      func.apply(this, args);
    },timeout);
  }
}
const doSearch = debounce((e)=>fetchData(e));
return (
    <div className='App'>
     <input type="text" onKeyUp={(e) => doSearch(e.target.value)} />
    </div>
);

12. Объяснение виртуального DOM

Когда вы вызываете setState() для компонента, указывая состояние, отличное от предыдущего, React помечает этот компонент как грязный. Это ключевой момент: React обновляет только тогда, когда компонент явно меняет состояние.

Что происходит дальше:

  • React обновляет виртуальный DOM относительно компонентов, помеченных как грязные (с некоторыми дополнительными проверками, такими как запуск shouldComponentUpdate())
  • Запускает алгоритм сравнения для согласования изменений
  • Обновляет реальный DOM

13. Однонаправленный поток данных против двунаправленного потока данных

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

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

React следует односторонней привязке данных с помощью реквизита.

В React это означает, что:

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

Пример:

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

import "./styles.css";
import {useState} from 'react';
const ChildComponent = (props) => {
  return(
    <>
    <input onChange={(e)=>props.handleCallback(e)} />
    </>
  )
}
export default function App() {
  const [name, setName] = useState();
const handleCallback = (e) => {
    setName(e.target.value);
  }
  return (
    <div className="App">
      <ChildComponent handleCallback={handleCallback}/>
      <h1>Hello {name}</h1>
    </div>
  );
}

14. Правила с JSX

JSX означает JavaScript XML. Это позволяет нам писать JavasScript с синтаксисом, похожим на HTML, а не HTML и не строку! без использования методов createElement() или appendChild().

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

Базовая единица JSX называется элементом JSX. Элементы JSX обрабатываются как выражения JavaScript. ЭлементJSX можно сохранить в переменной, передать функции или сохранить в объекте или массиве…

const myTeam = {
  center: <li>Benzo Walli</li>,
  powerForward: <li>Rasha Loa</li>,
  smallForward: <li>Tayshaun Dasmoto</li>,
  shootingGuard: <li>Colmar Cumberbatch</li>,
  pointGuard: <li>Femi Billon</li>
};

Каждый тег JSX преобразуется в вызов React.createElement и его объектное представление.

undefined, null и boolean не отображаются в пользовательском интерфейсе при использовании внутри JSX.

Вам нужно закрыть все теги

Как и в XHTML, если вы когда-либо использовали его, вам нужно закрыть все теги: больше не <br>, а вместо этого использовать самозакрывающийся тег: <br /> (то же самое касается других тегов).

camelCase — новый стандарт

В HTML вы найдете атрибуты без регистра (например, onchange). В JSX они переименованы в их эквивалент в camelCase:

  • onchange => onChange
  • onclick => onClick
  • onsubmit => onSubmit

class становится className

Из-за того, что JSX — это JavaScript, а class — зарезервированное слово, вы не можете написать

<p className="description">
  • class становится className
  • for становится htmlFor

потому что они являются зарезервированными словами в JavaScript.

Формы в JSX

JSX вносит некоторые изменения в работу HTML-форм, чтобы упростить работу разработчика.

Атрибут value всегда содержит текущее значение поля.

Атрибут defaultValue содержит значение по умолчанию, которое было установлено при создании поля.

<select defaultValue="x">
  <option value="x">...</option>
</select>

Пустое пространство в JSX

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

Чтобы решить эту проблему, вам нужно явно добавить пробел, добавив выражение пробела, подобное этому:

<p>
  Something
  {' '}becomes
  {' '}this
</p>
=======================OR=======================
<p>
  Something
  {' becomes '}
  this
</p>

Зацикленный элемент массива в JSX

Если у вас есть набор элементов, которые вам нужно зациклить для создания партиала JSX, вы можете создать цикл, а затем добавить JSX в массив:

const elements = ['one', 'two', 'three'];
return (
  <ul>
    {elements.map((value, index) => {
      return <li key={index}>{value}</li>
    })}
  </ul>
)

15. Пользовательские хуки:

// useFetch.js
import { useState, useEffect } from "react";
const useFetch = (url) => {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((data) => setData(data));
  }, [url]);
  return [data];
};
export default useFetch;

16. Государство

В конструкторе компонентов инициализируйте this.state. Например, компонент BlogPostExcerpt может иметь состояние clicked:

import React, {PureComponent} from "react";
class BlogPostExcerpt extends PureComponent {
  constructor(props) {
    super(props)
    this.state = { clicked: false }
  }
  
  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
}

Доступ и изменение состояния

Чтобы получить доступ к состоянию:

this.state.clicked

Чтобы изменить состояние:

this.setState({ clicked: true })

17. Перемещение состояния вверх по дереву (от дочернего к родительскому)

Состояние передается компонентам, которым нужно это значение, через реквизиты, и состояние может быть изменено дочерним компонентом путем передачи изменяющей функции в качестве реквизита:

class Converter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { currency: '€' }
  }
  
  handleChangeCurrency = event => {
    this.setState({ currency: this.state.currency === '€' ? '$' : '€' })
  }
  
  render() {
    return (
      <div>
        <Display currency={this.state.currency} />
        <CurrencySwitcher
          currency={this.state.currency}
          handleChangeCurrency={this.handleChangeCurrency}
        />
      </div>
    )
  }
}

const CurrencySwitcher = props => {
  return (
    <button onClick={props.handleChangeCurrency}>
      Current currency is {props.currency}. Change it!
    </button>
  )
}

const Display = props => {
  return <p>Current currency is {props.currency}.</p>
}

18. Реквизит

В компоненте класса реквизиты передаются по умолчанию. Нет необходимости добавлять что-то особенное, и они доступны как this.props в экземпляре компонента.

import React, { PureComponent } from 'react'
class ParentComponent extends PureComponent {
 render () {
  return(
   <ChildComponent title={"Java"} description={"hello world"}/>
  )
 }
}
class ChildComponent extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.props.description}</p>
      </div>
    )
  }
}

Чтобы получить доступ к свойствам внутри функциональных компонентов:

const ChildComponent = (props) => {
  return (
    <div>
        <h1>{props.title}</h1>
        <p>{props.description}</p>
      </div>
  )
}

Теперь вы можете получить доступ к этим реквизитам. Но! Вы не используете ключевое слово «это». Поскольку это не класс, вам не нужно ссылаться на сам компонент.

19. Деструктуризация реквизита

const ChildComponent = ({title, description}) => {
  return (
    <div>
        <h1>{title}</h1>
        <p>{description}</p>
      </div>
  )
}

20. Значения по умолчанию для реквизита

Если какое-либо значение не требуется, нам нужно указать для него значение по умолчанию, если оно отсутствует при инициализации Компонента.

ChildComponent.defaultProps = {
  title: '',
  description: ''
}

21. Передайте методы в качестве реквизита

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

const LoginButton = props => {
  return <Button text="Login" onClickHandler={props.onClickHandler} />
}
const Container = () => {
  const onClickHandler = () => {
    alert('clicked')
  }
  
  return <LoginButton onClickHandler={onClickHandler} />
}

22. Использование детского реквизита

Свойство props.children позволяет вставлять компоненты внутрь других компонентов. По сути, props.children используется для отображения всего, что вы включаете между открывающим и закрывающим тегами «содержащего» компонента при его вызове.

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

Компонент должен вывести props.children в свой JSX:

const Sidebar = props => {
  return <aside>{props.children}</aside>
}

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

<Sidebar>
  <Link title="First link" />
  <Link title="Second link" />
</Sidebar>

Однако здесь возникает проблема:невозможно получить доступ к состоянию родительского компонента из дочерних.

Пример: очень простым примером может быть Navbar, который может использовать children. Для Navbar элементы, которые ему необходимо отображать, а также порядок, выравнивание или элементы зависят от того, как его нужно использовать в разных экземплярах или на разных страницах. Например, Navbar где-то может иметь компонент поиска в одном месте, а в другом месте его может не быть. Кроме того, меню иногда могут быть нужны слева, за которым следует пункт меню «Вход» справа и панель поиска между ними, а иногда все они могут присутствовать справа без панели поиска. В таких случаях родительский компонент может управлять тем, как будет выглядеть внутренняя структура.

23. Рендер реквизит

Шаблон свойств рендеринга — это способ совместного использования функций между компонентами без повторения кода.

Термин «реквизит рендеринга» относится к методу совместного использования кода между компонентами React, использующего реквизит, значением которого является функция.

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

<SharedComponent 
 render = {
    (data) => ( 
      <h1> Hello {
            data.target
        } 
      </h1>
    )
}
/>

Реквизиты рендеринга означают, что вы передаете функцию рендеринга, определенную реквизитами отдельного компонента, чтобы указать, что должно быть возвращено общим компонентом.

import React from 'react';
const SharedComponent extends React.Component {
    render() {
        return ( 
            <div > {
                this.props.render()
            } 
            </div>
        );
    }
}
export default SharedComponent;

this.props.render() — это функция, переданная другим компонентом. Сама эта функция должна возвращать компонент React.

Вместо того, чтобы передавать компоненты как дочерние элементы родительского компонента, вы передаете функцию, которую затем выполняете в {this.props.render()}.

Ссылка:

24.Типы свойств

Так как JavaScript является динамически типизированным языком, у нас нет способа принудительно указать тип переменной во время компиляции, и если мы передаем недопустимые типы, они не будут выполняться во время выполнения или дадут странные результаты, если типы совместимы, но не то, что мы ожидаем.

import PropTypes from 'prop-types'
import React from 'react'

class BlogPostExcerpt extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.props.description}</p>
      </div>
    )
  }
}

BlogPostExcerpt.propTypes = {
  title: PropTypes.string.isRequired,
  description: PropTypes.string
}

export default BlogPostExcerpt

Добавление isRequired к любому параметру PropTypes приведет к тому, что React вернет ошибку, если это свойство отсутствует:

PropTypes.arrayOf(PropTypes.string).isRequired,
PropTypes.string.isRequired,

Другие случаи использования propTypes:

PropTypes.oneOfType([
  PropTypes.string,
  PropTypes.number
]),
=======================
PropTypes.oneOf(['Test1', 'Test2']),
=======================
PropTypes.instanceOf(Something)
=======================
PropTypes.node
======================= 
PropTypes.any 
=======================
PropTypes.arrayOf(PropTypes.string)
=======================
PropTypes.shape({
  color: PropTypes.string,
  fontSize: PropTypes.number
})

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

Вот основные типы, которые мы можем принять:

  • PropTypes.array
  • PropTypes.bool
  • PropTypes.func
  • PropTypes.number
  • PropTypes.object
  • PropTypes.string
  • PropTypes.symbol

25. Список и ключ

Чтобы отобразить список элементов, вы можете использовать метод map.

key — это необязательный prop, доступный для всех элементов. Он используется внутри React для отслеживания того, какие элементы были изменены. Для списков настоятельно рекомендуется добавлять key.

const people = [
  { id: 1, name: "Mike" },
  { id: 2, name: "Peter" },
  { id: 3, name: "John" },
];
const  App = () => {
    return people.map(({id,name}) => ( 
        <div key = {id}> 
             <h1>{name}<h1/>
        </div>
    ));
}

26. Презентационный компонент против компонентов-контейнеров

презентационные компоненты заботятся о внешнем виде, а контейнерные компоненты — о том, как заставить все работать.

Презентационный компонент может быть классовым или функциональным компонентом. но компоненты-контейнеры — это только типы классов.

Например, это презентационная составляющая. Он получает данные из своего реквизита и просто фокусируется на отображении элемента:

const Users = props => (
  <ul>
    {props.users.map(user => (
      <li>{user}</li>
    ))}
  </ul>
)

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

class UsersContainer extends React.Component {
  constructor() {
    this.state = {
      users: []
    }
  }
  
  componentDidMount() {
    axios.get('/users').then(users =>
      this.setState({ users: users }))
    )
  }
  
  render() {
    return <Users users={this.state.users} />
  }
}

27. Привязать обработчик событий с помощью 'this"

Если вы используете компоненты класса, не забудьте связать методы. Методы классов ES6 по умолчанию не привязаны. Это означает, что this не определено, пока вы не определите методы как стрелочные функции:

Синтаксис обычной функции изменяет контекст this ключевого слова. Когда вы пишете компонент класса, вы не можете вызывать this.setState без привязки вызывающей его функции. В противном случае он выдаст ошибку.

Это связано с тем, что this внутри handleClick() относится к контексту функции, а функция setState() является свойством класса App. Чтобы решить ошибку, вам нужно bind функцию this.handleClick, когда вы передаете ее в реквизит onClick:

Привязка обработчика событий внутри конструктора:

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      name: "Johnson"
    }
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick(){
    this.setState({name: "Jack"})
  }

  render(){
    return (
      <div>
        <p>My name is {this.state.name}</p>
        <button onClick={this.handleClick}>
          Change name
        </button>
      </div>
    )
  }
}

Привязка при вызове eventHandler:

class App extends React.Component {
  state = {
    name: "Johnson"
  }

  handleClick(){
    this.setState({name: "Jack"})
  }

  render(){
    return (
      <div>
        <p>My name is {this.state.name}</p>
        <button onClick={this.handleClick.bind(this)}>
          Change name
        </button>
      </div>
    )
  }
}

Использование функции стрелки:

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

handleClick = () => {
  this.setState({name: "Jack"})
}

render(){
  return (
    <div>
      <p>My name is {this.state.name}</p>
      <button onClick={this.handleClick}>
        Change name
      </button>
    </div>
  )
}

Передача функции Arrow в рендере вызывает проблему:

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

handleClick(){
  this.setState({name: "Jack"})
}

render(){
  return (
    <div>
      <p>My name is {this.state.name}</p>
      <button onClick={() => this.handleClick()}>
        Change name
      </button>
    </div>
  )
}

28. получить производное состояние от пропса ()

Когда состояние зависит от реквизита, можно использовать getDerivedStateFromProps для обновления состояния на основе значения реквизита.

В этом методе у вас нет доступа к this, так как это статический метод.

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

29. Контролируемые и неконтролируемые компоненты

В React есть два основных способа обработки форм, которые различаются на фундаментальном уровне: как управляются данные.

  • если данные обрабатываются DOM, мы называем их неуправляемыми компонентами
  • если данные обрабатываются компонентами, мы называем их управляемыми компонентами

Когда состояние элемента изменяется в поле формы, управляемом компонентом, мы отслеживаем это с помощью атрибута onChange.

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = { username: '' }
  }
  
  handleChange(event) {}
  
  render() {
    return (
      <form>
        Username:
        <input
          type="text"
          value={this.state.username}
          onChange={this.handleChange}
        />
      </form>
    )
  }
}

В этом случае вам нужно получить ссылку на поле, назначив атрибут ref свойству, определенному в конструкторе с помощью React.createRef(), и использовать его, чтобы получить его значение в обработчике отправки:

class FileInput extends React.Component {
  constructor(props) {
    super(props)
    this.curriculum = React.createRef()
    this.handleSubmit = this.handleSubmit.bind(this)
  }
  
  handleSubmit(event) {
    event.preventDefault();
    alert(this.curriculum.current.files[0].name);
  }
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="file" ref={this.curriculum} />
        <input type="submit" value="Submit" />
      </form>
    )
  }
}

Это способ неконтролируемых компонентов. Состояние хранится в DOM, а не в состоянии компонента (обратите внимание, что мы использовали this.curriculum для доступа к загруженному файлу и не трогали state.

30. Контекстный API

Вы создаете контекст, используя React.createContext(), который возвращает объект Context:

const { Provider, Consumer } = React.createContext()

Затем вы создаете компонент-оболочку, который возвращает компонент Provider, и добавляете в качестве дочерних все компоненты, из которых вы хотите получить доступ к контексту:

class Container extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      something: 'hey'
    }
  }
  
  render() {
    return (
      <Provider value={{ state: this.state }}>
       {this.props.children}           
      </Provider>
    )
  }
}

class HelloWorld extends React.Component {
  render() {
    return (
      <Container>
        <Button />
      </Container>
    )
  }
}

При использовании нескольких файлов вы создаете контент в одном файле и импортируете его во все места, где вы его используете:

//context.js
import React from 'react'
export default React.createContext()

//component1.js
import Context from './context'
//... use Context.Provider

//component2.js
import Context from './context'
//... use Context.Consumer

31. Разделение кода, отложенная загрузка или динамический импорт

Что происходит по умолчанию, когда вы отправляете современное веб-приложение, созданное с использованием пакета Webpack.

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

Разделение кода – это загрузка того кода JavaScript, который вам нужен, только в тот момент, когда он вам нужен.

React.lazy и Suspense представляют собой идеальный способ ленивой загрузки зависимости и загрузки ее только при необходимости. Suspense — это компонент, который можно использовать для обертки любого лениво загружаемого компонента. Используйте его fallback для вывода некоторого JSX или вывода компонента.

import React from 'react'
import { BrowserRouter, Routes, Route } from 'react-router-dom'

const TodoList = React.lazy(() => import('./routes/TodoList'))
const NewTodo = React.lazy(() => import('./routes/NewTodo'))

const App = () => (
  <BrowserRouter>
    <React.Suspense fallback={<p>Please wait</p>}>
      <Routes>
        <Route exact path="/" element={<TodoList/>} />
        <Route path="/new" element={<NewTodo/>} />
      </Routes>
    </React.Suspense>
  </BrowserRouter>
)

компонент TodoList будет динамически добавлен к выходным данным, как только он станет доступен. Webpack создаст для него отдельный пакет и позаботится о его загрузке при необходимости.

32. Стилизация с использованием модулей CSS

Начните с создания файла CSS, оканчивающегося на .module.css, например Button.module.css. Отличный выбор — дать ему то же имя, что и компоненту, который вы собираетесь стилизовать.

Добавьте сюда свой CSS, а затем импортируйте его в файл компонента, который вы хотите стилизовать:

import style from './Button.module.css'
const Button = () => {
  return <button className={style.content}>A button</button>
}

33. Декларативный

React сделал свой «декларативный подход» довольно популярным и авантюрным, поэтому он проник во внешний мир вместе с React.

  • вы можете создавать веб-интерфейсы, даже не касаясь DOM напрямую
  • вы можете иметь систему событий, не взаимодействуя с реальными событиями DOM.

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

34. Неизменность

В программировании переменная считается неизменной, если ее значение не может измениться после ее создания.

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

Неизменяемая переменная никогда не может быть изменена. Чтобы обновить его значение, вы создаете новую переменную.

То же самое относится к объектам и массивам.

Вместо изменения массива для добавления нового элемента вы создаете новый массив, объединяя старый массив и новый элемент.

Объект никогда не обновляется, а копируется перед его изменением.

Когда вы добавляете к массиву или объекту, вы не переназначаете или повторно объявляете константу, она уже объявлена ​​и назначена, вы просто добавляете в «список», на который указывает константа.

Итак, это будет рабочий файл:

const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
====================================
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']

Но ниже код выдаст ошибку:

const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared

35. Маршрутизация

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

  1. Существует множество типов компонентов Router, например ‹BrowserRouter› и ‹ HashRouter› для клиентских приложений React. Если вы используете динамический сервер, который может обрабатывать динамические URL-адреса, вам необходимо использовать компонент BrowserRouter, но если вы используете сервер, который обслуживает только статические файлы, тогда В этом случае следует использовать компонент >HashRouter.
  2. Всякий раз, когда вы хотите перенаправить в другое место, вы можете разместить компонент, который при рендеринге будет перенаправляться в местоположение, указанное в свойстве to, которое может быть либо строкой, либо объектом местоположения, например:
<Redirect to="/register"/>

3. Вы также можете перемещаться внутри своего приложения React, используя методы из объекта history, например:

history.push("/my-path") 
history.replace("/my-path")

что эквивалентно следующему: компонент Link принимает свойство to, которое сообщает React Router место назначения для перехода.

<Link to="/my-path"/> 
<Redirect to="/my-path"/>

Защищенный маршрут:

import Admin from "./admin";
import Display from "./display";
import { BrowserRouter, Routes, Route } from "react-router-dom";
const Protected = ({auth, children }) => {   
    return auth ? children : <Navigate to="/login" />;
    // here children is Admin Component to be render
}
const MainRoute = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route 
            element={ 
            <Protected auth={isLoggedIn}>
              <Admin />
            </Protected>} 
            path="" 
         />
        <Route element={<Display />} path="display" />
      </Routes>
    </BrowserRouter>
  );
};
export default MainRoute;

36. Компоненты маршрутизатора React:

1. Ссылка: <Link> – это элемент, который позволяет пользователю перейти на другую страницу, щелкнув или коснувшись ее.

<Link to={user.id}>{user.name}</Link>

2. NavLink: <NavLink> — это особый вид <Link>, который знает, является ли он «активным».

<NavLink
  to="messages"
  style={({ isActive }) =>
        isActive ? activeStyle : undefined
 }>
 Messages
</NavLink>

3. Навигация: элемент <Navigate> меняет текущее местоположение при визуализации.

{user && (
   <Navigate to="/dashboard" replace={true} />
)}

4.Маршруты и маршрут:

<Routes>
  <Route path="/" element={<Dashboard />}>
    <Route path="messages" element={<DashboardMessages />}/>
    <Route path="tasks" element={<DashboardTasks />} />
  </Route>
  <Route path="about" element={<AboutPage />} />
</Routes>

37. Крючки маршрутизатора React:

  1. useRoutes: он использует объекты JavaScript вместо элементов <Route> для определения ваших маршрутов.
let element = useRoutes([
    {
      path: "/",
      element: <Dashboard />,
      children: [
        {
          path: "messages",
          element: <DashboardMessages />,
        },
        { path: "tasks", element: <DashboardTasks /> },
      ],
    },
    { path: "team", element: <AboutPage /> },
  ]);

  return element;

2. использовать навигацию

3.useParams

4. использоватьместоположение

38. Тестирование:

@testing-library/react: Библиотека тестирования React — это служебный инструмент тестирования, созданный для тестирования фактического дерева DOM, отображаемого React в браузере.

Библиотека тестирования React не привязана к какой-либо среде тестирования, мы можем использовать любой инструмент для запуска тестов, например jest, mocha.

import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});

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

  • getByText(): найти элемент по его значению textContent
  • getByRole(): по значению атрибута role
  • getByLabelText(): по значению атрибута label
  • getByPlaceholderText(): по значению атрибута placeholder
  • getByAltText(): по значению атрибута alt
  • getByDisplayValue(): по атрибуту value, обычно для <input> элементов
  • getByTitle(): по значению атрибута title

А когда этих методов недостаточно, можно использовать метод getByTestId(), который позволяет найти элемент по его атрибуту data-testid:

import { render, screen } from '@testing-library/react';

render(<div data-testid="custom-element" />);
const element = screen.getByTestId('custom-element');

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

import React, { useState } from "react";

function App() {
  const [theme, setTheme] = useState("light");

  const toggleTheme = () => {
    const nextTheme = theme === "light" ? "dark" : "light";
    setTheme(nextTheme);
  };

  return <button onClick={toggleTheme}>
      Current theme: {theme}
    </button>;
}

export default App;
==================================================================
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import App from "./App";

test("Test theme button toggle", () => {
  render(<App />);
  const buttonEl = screen.getByText(/Current theme/i);
    
  userEvent.click(buttonEl);
  expect(buttonEl).toHaveTextContent(/dark/i);
});

здесь, как только кнопка нажата, вы можете подтвердить, что тест прошел успешно, проверив, содержит ли текст элемента кнопки «темный» или нет.

39.GraphQL:

Самая популярная и всеобъемлющая библиотека GraphQL — Apollo Client. Чтобы начать работу с Apollo Client, вам необходимо установить как основную зависимость Apollo Client, так и GraphQL:

npm install @apollo/client graphql

Когда вы создаете свой клиент Apollo, вам нужно указать значение uri, а именно конечную точку GraphQL. Дополнительно нужно указать кеш.

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

import React from "react";
import ReactDOM from "react-dom";
import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";

import App from "./App";

const client = new ApolloClient({
  uri: "https://api.spacex.land/graphql/",
  cache: new InMemoryCache()
});

const rootElement = document.getElementById("root");
ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  rootElement
);

Поскольку здесь вы просто запрашиваете данные, вы будете использовать хук useQuery. После выполнения этого запроса вы получите значения data, loading и error:

import React from "react";
import { useQuery, gql } from "@apollo/client";

const FILMS_QUERY = gql`
  {
    launchesPast(limit: 10) {
      id
      mission_name
    }
  }
`;

export default function App() {
  const { data, loading, error } = useQuery(FILMS_QUERY);

  if (loading) return "Loading...";
  if (error) return <pre>{error.message}</pre>

  return (
    <div>
      <h1>SpaceX Launches</h1>
      <ul>
        {data.launchesPast.map((launch) => (
          <li key={launch.id}>{launch.mission_name}</li>
        ))}
      </ul>
    </div>
  );
}

40. Модули узла для реакции:

  1. реакция-маршрутизатор-дом
  2. редукс
  3. редукционный преобразователь
  4. формик
  5. ага
  6. фреймер-движение
  7. реакция-бутстрап
  8. стилизованный компонент
  9. ESLint
  10. реагировать-i18next
  11. редукс-от
  12. аксиомы
  13. библиотека для тестирования реакции
  14. шутка

Если вы нашли эту статью полезной, пожалуйста, похлопайте в ладоши и поделитесь ею с другими. Спасибо за прочтение.

Создавайте приложения с повторно используемыми компонентами, такими как Lego.

Инструмент с открытым исходным кодом Bit помогает более чем 250 000 разработчиков создавать приложения с компонентами.

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

Подробнее

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

Микро-интерфейсы

Система дизайна

Совместное использование кода и повторное использование

Монорепо

Узнать больше