Рубрики
Без рубрики

Коллекция новичков мощных советов и трюков для реагирования

Это является частью моей «реагирования на новичков» серии «Начинающие» при введении реагирования, его основных функций и лучших практик для последующей деятельности. Допускаются больше статей! << Начать все сначала | <Превосходство Вы можете сказать по названию этой статьи, она нацелена на начинающих. На самом деле, я начал учиться реагировать

Автор оригинала: FreeCodeCamp Community Member.

Как вы можете сказать из названия этой статьи, она нацелена на начинающих.

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

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

Назовите ваши компоненты

Чтобы понять, какой компонент имеет ошибку, важно всегда дать вашему компоненту имя.

Еще больше, когда вы начинаете использовать React Router или сторонние библиотеки.

// Avoid thoses notations 
export default () => {};
export default class extends React.Component {};

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

Независимо от того, как вы подвергаете свой компонент, назовите его

Вам необходимо определить имя класса или имя переменной (для функциональных компонентов), которые хостит компонент.

Реагировать на самом деле Выведите имя компонента От него в сообщениях об ошибках.

export const Component = () => 

I'm a component

; export default Component; // Define user custom component name Component.displayName = 'My Component';

Вот мой последний совет по поводу импорта (взятых из здесь ): Если вы используете ESLINT, вы должны рассмотреть возможность установки следующих двух правил:

"rules": {
    // Check named import exists
    "import/named": 2, 
  
    // Set to "on" in airbnb preset
    "import/prefer-default-export": "off"
}

Предпочитаю функциональные компоненты

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

class Watch extends React.Component {
  render () {
    return 
{this.props.hours}:{this.props.minutes}
} } // Equivalent functional component const Watch = (props) =>
{props.hours}:{props.minutes}
;

Обе фрагменты определяют то же самое Смотреть составная часть. Тем не менее, второй путь короче и даже падает это Для доступа к реквизиту в шаблоне JSX.

Замените девсы с фрагментами

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

Rect 16 приносит нам новую функцию под названием Фрагменты Отказ Теперь вы можете заменить эти бесполезные Div с Реагировать S Отказ

Выходной шаблон будет содержанием фрагмента без какого-либо обертки.

const Login = () => 
  
; const Login = () => ; const Login = () => // Short-hand syntax <>;

Будьте осторожны, установив состояние

Как только ваше приложение React является динамичным, вы должны иметь дело с государствами компонентов.

Использование состояний кажется довольно простым. Инициализировать содержание состояния в Конструктор а потом звоните SetState Обновить состояние Отказ

По какой-то причине вам может потребоваться использовать текущий Государство или реквизит Значения при звонке SetState установить значение следующего состояния.

// Very bad pratice: do not use this.state and this.props in setState !
this.setState({ answered: !this.state.answered, answer });

// With quite big states: the tempatation becomes bigger 
// Here keep the current state and add answer property
this.setState({ ...this.state, answer });

Вопрос в том, что реагирование не гарантирует Это и Это .props иметь значение, которое вы ожидаете. SetState Асинхронный, потому что государственные обновления являются пакетными, чтобы оптимизировать манипуляции DOM (см. Детали в документе React Docs И это Выпуск ).

// Note the () notation around the object which makes the JS engine
// evaluate as an expression and not as the arrow function block
this.setState((prevState, props) 
              => ({ ...prevState, answer }));

Чтобы предотвратить поврежденные состояния, вы должны использовать SetState с функциональным параметром. Он обеспечивает правильные значения состояния и реквизиты.

Функции связывания компонента

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

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

class DatePicker extends React.Component {
   handleDateSelected({target}){
     // Do stuff
   }
   render() {   
     return 
   }
 }

Это может разочаровать вас, когда вы узнаете, что он не работает.

Причина в том, что при использовании JSX, это Значение не связано с экземпляром компонента. Вот три альтернативы, чтобы сделать его работать:

// #1: use an arrow function
 this.handleDateSelected(event)}/>

// OR #2: bind this to the function in component constructor
constructor () { 
  this.handleDateSelected = this.handleDateSelected.bind(this); 
}

// OR #3: declare the function as a class field (arrow function syntax)
handleDateSelected = ({target}) => {
   // Do stuff
}

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

Также будьте осторожны о последнем решении. Он использует синтаксис классов полей, который является только Предложение по Ecmascript Отказ

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

Принять контейнер-шаблон (даже с redux)

Последнее, но не меньше всего, узор дизайна контейнера. Это позволяет вам следовать за Разделение опасений Принцип в области реагирования.

export class DatePicker extends React.Component {
  state = { currentDate: null };

  handleDateSelected = ({target}) =>
     this.setState({ currentDate: target.value });

  render = () => 
     
}

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

const DatePicker = (props) => 
  
        
export class DatePickerController extends React.Component { 
  // ... No changes except render function ...
  render = () => 
     ;
}

Вот трюк. DatePickerContainer При необходимости обрабатывает связи пользовательских взаимодействий и API. Тогда он делает DatePicker и поставляет реквизиты.

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

export const DatePickerContainer = 
 connect(mapStateToProps, mapDispatchToProps)(DatePickerController);

Кроме того, если вы используете Redux в качестве State Manager для вашего приложения, он также хорошо подключается с этим шаблоном.

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

Таким образом, оба компонента смогут доступа к данным Redux. Вот полный код для рисунка дизайна контейнера (без синтаксиса полей Redux или классов).

Бонус: исправить бурение

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

Как глубоко вложенные тупые компоненты получают доступ к основным компонентам данных? На самом деле, они не могут – но вы можете исправить это по:

  • Обогатив тупой компонент в контейнере (становится умным)
  • или пропустить реквизиты от верхнего компонента

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

const Page = props => ;
   
const UserDetails = props => 

User details

// <= No need fullName but pass it down
; const inputStyle = { height: '30px', width: '200px', fontSize: '19px', border: 'none', borderBottom: '1px solid black' }; const CustomInput = props => // v Finally use fullName value from Page component ;

Общественное сообщество по имени этот вопрос Пропор бурение Отказ

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

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

Не волнуйтесь, я собираюсь научить вас три способа это исправить. Две первые методы появляются в Документация контекста API : Дети опоры и Рендер опора Отказ

// #1: Use children prop
const UserDetailsWithChildren = props => 

User details (with children)

{props.children /* <= use children */}
; // #2: Render prop pattern const UserDetailsWithRenderProp = props =>

User details (with render prop)

{props.renderFullName() /* <= use passed render function */}
; const Page = () => {/* #1: Children prop */} {/* Defines props.children */} {/* #2: Render prop pattern */} {/* Remember: passing arrow functions is a bad pratice, make it a method of Page class instead */} }/> ;

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

const Page = () =>  

   
    
      
          
      
    
  

Третий пример использует экспериментальный контекст API.

const UserFullNameContext = React.createContext('userFullName');

const Page = () => 
 {/* Fill context with value */}
    
;

const UserDetailsWithContext = () => // No props to provide

User details (with context)

{/* Get context value */} { fullName => }
;

Я не рекомендую этот метод, потому что он использует экспериментальную функцию. (И именно поэтому API недавно изменился на второстепенной версии .) Кроме того, он заставляет вас создавать глобальную переменную для хранения контекста, и ваш компонент получает неясную новую зависимость (контекст может содержать что-либо).

Это оно!

Спасибо за прочтение. Я надеюсь, вы узнали некоторые интересные советы по реагированию!

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

Не забудьте следовать за мной, чтобы получить уведомление о моих предстоящих статьях ?

Проверьте мои другие статьи

➥ JavaScript

➥ Советы и трюки