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

Как работать с реагированием правильного способа избежать некоторых распространенных подводных камней

Фото Alexander Sinn / Unsplashone, что я слышу довольно часто – «Давайте пойдем на redux» в нашем новом приложении React React. Это помогает вам масштабировать, и данные приложений не должны быть в локальном состоянии реагирования, потому что оно неэффективно. Или когда вы называете API и в то время как обещание

Автор оригинала: Adeel Imran.

Одна вещь, которую я слышу довольно часто, это « Пойдем на redux «В нашем новом приложении React React. Это помогает вам масштабировать, и данные приложений не должны быть в локальном состоянии реагирования, потому что оно неэффективно. Или когда вы называете API и Хотя обещание ожидается, компонент становится размонтированным, и вы получаете следующую красивую ошибку.

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

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

Дэн даже согласен Отказ

Я люблю реагировать, и я работаю над этим почти два года. До сих пор нет сожалений. Лучшее решение когда-либо. Мне нравится Vue и все классные библиотеки/каркасы там. Но реагировать удерживает особое место в моем сердце. Это помогает мне сосредоточиться на работе, которую я должен сделать, а затем занимать все свое время в манипуляциях Дома. И это делает это в лучшем и наиболее эффективном способе. С его Эффективное примирение Отказ

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

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

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

Моя цель для этой статьи – убедиться, что никто никогда не должен столкнуться с этой ошибкой, а не знать, что делать с этим снова.

Что мы рассмотрим

  • Четкие подписки, такие как SettimeOut/Setinterval
  • Прозрачные асинхронные действия, когда вы называете запрос XHR, используя принести или библиотеки, как Axios.
  • Альтернативные методы, некоторые самые популярные другие устарели.

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

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

Так что теперь давайте прыгнем на начало.

1: Четкие подписки

Давайте начнем с примера:

Давайте поговорим о том, что только что произошло здесь. То, что я хочу, чтобы вы сосредоточены на том, это Counter.js Файл, который в основном увеличивает счетчик через 3 секунды.

Это дает ошибку за 5 секунд, потому что я размонтировал подписку без очистки. Если вы хотите снова увидеть ошибку, просто нажмите кнопку «Обновить» в редакторе CodeSandbox, чтобы увидеть ошибку в консоли.

У меня есть мой контейнерный файл index.js который просто переключает счетчик составляющей после первых пяти секунд.

Так

В моем index.js я называю counter.js и просто делаю это в моем визуализации:

{showCounter ?  : null}

ShowCounter. Государственный булевой, который настроен на ложь после первых 5 секунд, как только компонент монтируется (ComponentDIDMount).

Настоящая вещь, которая иллюстрирует нашу проблему, здесь Counter.js Файл, который увеличивает количество после каждые 3 секунды. Так что после первых 3 секунды обновления счетчиков. Но как только он попадет ко второму обновлению, которое происходит в 6-м Во-вторых, index.js Файл уже размонтировал счетчик счетчиков в 5-м второй. К тому времени, когда счетчик счетчика достигает 6-го Во-вторых, он обновляет счетчик во второй раз.

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

Теперь, если вы новичок, чтобы реагировать, вы можете сказать: «Хорошо Adeel … Ага Но разве мы не просто размонтилировали счетчик составляющей на 5-й секунду? Если нет компонента для счетчика, как это может это государство все еще обновить на шестой секунде?

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

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

Лучший способ очистить эти виды подписок в вашем ComponentWillunmount жизненный цикл. Вот пример того, как вы можете сделать это. Проверьте метод ComponentWillunmount ComponentWillunmount файла Counter.js:

И это в значительной степени это для Settimout & Setinterval Отказ

2: API (XHR) Прервать

  • Уродливый старый подход (устаревший)
  • Хороший более новый подход (основная цель для этой статьи)

Итак, мы обсуждали подписки. Но что, если вы сделаете асинхронный запрос? Как вы отмените его?

По старому

Прежде чем я говорю об этом, я хочу поговорить о устаревшем методе реагировать ismounted ()

До декабря 2015 года был под названием метод ismounted в реакции. Вы можете прочитать больше об этом в React блог . Что это было, было что-то подобное:

import React from 'react'
import ReactDOM from 'react-dom'
import axios from 'axios'

class RandomUser extends React.Component {
  state = {user: null}
  _isMounted = false
  handleButtonClick = async () => {
    const response = await axios.get('https://randomuser.me/api/')
    if (this._isMounted) {
      this.setState({ user: response.data })
    }
  }
  componentDidMount() {
    this._isMounted = true
  }
  componentWillUnmount() {
    this._isMounted = false
  }
  render() {
    return (
      
{JSON.stringify(this.state.user, null, 2)}
) } }

Для этого примера я использую библиотеку под названием Axios для создания запроса XHR.

Давайте пройдем через это. Я изначально установил This_ismounted к ложь Прямо рядом с тем, где я инициализировал мое состояние. Как только жизненный цикл ComponentDidmount позывается, я установил Это._ismounted правда. В течение этого времени, если конечный пользователь нажимает кнопку, производится запрос XHR. Я использую RandomUser.me Отказ Как только обещание будет решено, я проверяю, все еще установлен компонент This_ismounted Отказ Если это правда, я обновляю свое состояние, в противном случае я игнорирую его.

Пользователь может щелкнуть на кнопке, когда был разрешен асинхронный вызов. Это приведет к тому, что пользовательские страницы переключения пользователей. Итак, чтобы избежать ненужного государственного обновления, мы можем просто справиться с этим в нашем методе жизненного цикла ComponentWillunmount Отказ Я просто устанавливаю Это._ismounted к ложе. Итак, всякий раз, когда вызов асинхронного API будет решен, он проверит, будет ли This_ismounted неверно И тогда он не будет обновлять состояние.

Этот подход делает работу, но, как говорят реагирование:

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

Давайте поговорим о правильном пути

Здесь, чтобы спасти день – Abortcontrollers. . Согласно MDN Документация IT:

Давайте рассмотрим немного более подробно здесь. С кодом, конечно, потому что все ❤ код.

var myController = new AbortController();
var mySignal = myController.signal;

var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function() {
  myController.abort();
  console.log('Download aborted');
});

function fetchVideo() {
  ...
  fetch(url, { signal: mySignal }).then(function(response) {
    ...
  }).catch(function(e) {
    reports.textContent = 'Download error: ' + e.message;
  })
}

Сначала мы создаем Новый abortcontroller и назначить его переменной под названием MyController Отказ Тогда мы делаем сигнал Для этого abortcontroller. Подумайте о сигнале как индикатор, чтобы сообщить нашим XHR-запросам, когда пришло время прервать запрос.

Предположим, что у нас есть 2 кнопки, Скачать и Прервать Отказ Кнопка загрузки загружает видео, но, если, если при загрузке мы хотим отменить запрос на скачивание? Нам просто нужно позвонить mycontroller.abort () Отказ Теперь этот контроллер прерывает все запросы, связанные с ним.

Как, вы можете спросить?

После того, как мы сделали var abortcontroller () Мы сделали это var.signal Отказ Теперь в моем запросе, где я говорю ей URL и полезную нагрузку, мне просто нужно пройти Mysignal ссылаться/сигнал что Извлекать Запрос с моим удивительным Abortcontroller Отказ

Если вы хотите прочитать еще более обширный пример о Abortcontroller. , классные люди на MDN У этого действительно хороший и элегантный пример на их Github. Вы можете проверить это здесь Отказ

Я хотел поговорить об этих запросах прерваний, потому что не так много людей осознают их. Запрос на прерску в Fetch начался в 2015 году. Вот …| Оригинальная проблема GitHub на Abort – Он наконец получил поддержку около октября 2017 года. Это разрыв двух лет. Ух ты! Есть несколько библиотек, таких как Axios. которые придают поддержку AbortController. Я буду обсуждать, как вы можете использовать его с Axios, но я впервые хотел показать углубленную версию под ключ, как работает AbortController.

Преподавая запрос XHR в Axios

Реализация, которую я говорил выше, не специфичен для реагирования, но вот что мы обсудим здесь. Основная цель этой статьи состоит в том, чтобы показать вам, как очистить ненужные манипуляции DOM в реакции, когда запрос XHR сделан, и компонент не размонтируется, пока запрос находится в ожидании состояния. Whaw!

Так что без дальнейшего ADO, здесь мы идем.

import React, { Component } from 'react';
import axios from 'axios';

class Example extends Component {
  signal = axios.CancelToken.source();

  state = {
    isLoading: false,
    user: {},
  }
  
  componentDidMount() {
    this.onLoadUser();
  }
  
  componentWillUnmount() {
    this.signal.cancel('Api is being canceled');
  }
  
  onLoadUser = async () => {
    try {
      this.setState({ isLoading: true });
      const response = await axios.get('https://randomuser.me/api/', {
        cancelToken: this.signal.token,
      })
      this.setState({ user: response.data, isLoading: true });
    } catch (err) {
      if (axios.isCancel(err)) {
        console.log('Error: ', err.message); // => prints: Api is being canceled
      } else {
        this.setState({ isLoading: false });
      }
    }
   } 
   
    
    render() {
      return (
        
{JSON.stringify(this.state.user, null, 2)}
) } }

Давайте пройдем через этот код

Я установил this.signal к Axios.cancelkoken.Source () Что в основном создает новую Abortcontroller и назначает сигнал этого Abortcontroller к this.signal Отказ Далее я называю методом в ComponentDidmount называется this.onloaduser () которые вызывает случайную информацию о пользователе от третьей стороны API RandomUser.me Отказ Когда я называю это API, я также передаю сигнал к недвижимости в Axios, называемых отмен

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

Теперь запрос был в ожидании (то есть это не было разрешено или отклонено, но пользователь решил перейти на другую страницу. Как только метод жизненного цикла ComponentWillunmount Призывается, мы прервавшим нашим запросом API. Как только API получит прерванный/отмененный, обещание будет отклонено, и он будет приземлиться в поймать Блок этого попробуйте/поймать Заявление, особенно в если (axios.iscancel (err) {} блок.

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

P.S: Вы можете использовать тот же сигнал и передавать его как можно больше XHR в вашем компоненте, как вам нравится. Когда компонент получает установленные ООН, все эти запросы XHR, которые находятся в отложенном состоянии, будут отменены при вызове ComponentWillUnmount.

Окончательные детали

Поздравляю!:) Если вы прочитали это далеко, вы только что узнали, как прервать запрос XHR на своих собственных условиях.

Давайте продолжим немного больше. Обычно ваши запросы XHR находятся в одном файле, и ваш основной компонент контейнера находится в другом (из которого вы называете этот метод API). Как вы проходите этот сигнал в другой файл и все равно получите этот запрос XHR?

Вот как вы это делаете:

import React, { Component } from 'react';
import axios from 'axios';

// API
import { onLoadUser } from './UserAPI';

class Example extends Component {
  signal = axios.CancelToken.source();

  state = {
    isLoading: false,
    user: {},
  }
  
  componentDidMount() {
    this.onLoadUser();
  }
  
  componentWillUnmount() {
    this.signal.cancel('Api is being canceled');
  }
  
  onLoadUser = async () => {
    try {
      this.setState({ isLoading: true });
      const data = await onLoadUser(this.signal.token);
      this.setState({ user: data, isLoading: true });
    } catch (error) {
      if (axios.isCancel(err)) {
        console.log('Error: ', err.message); // => prints: Api is being canceled
      } else {
        this.setState({ isLoading: false });
      }
    }
  }
    
    render() {
      return (
        
{JSON.stringify(this.state.user, null, 2)}
) } }; }
export const onLoadUser = async myCancelToken => {
  try {
    const { data } = await axios.get('https://randomuser.me/api/', {
      cancelToken: myCancelToken,
    })
    return data;
  } catch (error) {
    throw error;
  }
};

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

Спасибо, что вы получили время прочитать. Кричать в мою очень талантливый коллега Кинань Для того, чтобы помочь мне доказательство прочитать эту статью. Благодаря К Ent C Dodds Для того, чтобы быть вдохновением в сообществе JavaScript OSS.

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

Также есть Еще один удивительный читал на Abort Controller что я нашел через MDN Документация по Джейк Арчибальд . Я предлагаю вам прочитать его, если у вас любопытный характер, как моя.

Оригинал: “https://www.freecodecamp.org/news/how-to-work-with-react-the-right-way-to-avoid-some-common-pitfalls-fc9eb5e34d9e/”