как вы можете реорганизовать для использования классов

kak vy mozhete reorganizovat dlya ispolzovaniya klassov

В небольших проектах React хорошо храните все ваши методы компонентов в самих компонентах. В проектах среднего размера вы можете изъявить желание извлечь эти методы из своих компонентов и превратить их в «помощника». Здесь я покажу вам, как использовать класс (вместо экспорта отдельных функций и переменных) для организации кода.

Примечание: Я работаю в React, поэтому это пример, который мы здесь обсудим.

Типичный рефакторинг

В типичном рефакторинге вы берете функцию для компонента и перемещаете ее в другой помощник.

От:

const MyComponent = () => {
  const someFunction = () => 'Hey, I am text'
  return (
    <div>
      {someFunction()}
    </div>
  )
}

Кому:

import { someFunction } from 'functionHelper.js'
const MyComponent = () => {
  return (
    <div>
      {someFunction()}
    </div>
  )
}

и

export const someFunction = () => 'Hey, I am text'

Этот пример действительно нелеп, но вы видите, куда мы идем:

  1. Возьмите свои функции и скопируйте их в отдельный файл
  2. Импортируйте их и называйте их как обычные.

Однако когда все становится сложным, вам придется передать этим функциям кучу вещей — объекты, функции для манипулирования состоянием и т.д. Сегодня я столкнулся с проблемой, когда я хотел извлечь три функции из компонента, и все они требовали одинаковых входных данных (a resource и функция обновления resource). Должен быть лучший способ…

Рефакторинг с классом

Я сделал большую демонстрацию этой публикации. Вы можете просмотреть код на Github. Первоначальный комит показывает всю функциональность внутри основного компонента (App.js) и последующий фиксирует рефакторинг кода для использования класса.

gYagZlg9McGFcj763-OOKtIBZjjiGEoOLbjZ

Вы можете запустить это самостоятельно и делать все, что вы хотите. Не забывайте yarn install.

Мы начинаем с компонента, который «извлекает» объект (имитируя то, как мы можем это делать с API) с определенными атрибутами: повтор (количество полей), сторона (высота и ширина), текст, цвет. Затем у нас есть несколько способов манипулирования видом – изменение цвета, обновление текста и т.д. После каждой смены мы отображаем сообщение.

Например, вот наш метод изменения ширины и высоты:

changeSide = side => {
  const obj = {...this.state.obj, side}
  this.fetchObject(obj);
  this.setState({ message: `You changed the sides to ${side} pixels!` });
}

У нас может быть ряд других методов, требующих подобных действий или, возможно, совсем других методов. Мы можем начать думать, чтобы получить этот код к помощнику. Тогда мы создали бы другой метод для вызова setState действие, и мы должны его пройти, this.fetchObjectобъект в состоянии и side мы получаем в качестве аргумента к методу. Если у нас есть несколько подобных методов, это много параметров для передачи, и, возможно, это не так полезно (или читабельно).

Вместо этого мы можем использовать класс с методом конструктора:

export default class ObjectManipulator {
  constructor( { object, fetchObject, markResettable, updateMessage, updateStateValue } ) {
    this.fetchObject = fetchObject;
    this.markResettable = markResettable;
    this.updateMessage = updateMessage;
    this.updateStateValue = updateStateValue;
  }

  changeSide = ( object, side ) => {
    const newObject = { ...object, side };
    this.fetchObject(newObject);
    this.updateMessage(`You changed the sides to ${side} pixels!`);
    this.markResettable();
    this.updateStateValue('side', side);
  };
};

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

const manipulator = new ObjectManipulator({
  object,
  fetchObject: this.fetchObject,
  markResettable: this.markResettable,
  updateMessage: this.updateMessage,
  updateStateValue: this.updateStateValue,
});

Это создает объект manipulator — экземпляр нашего ObjectManipulator класс. Когда мы звоним manipulator.changeSide(object, '800') он будет запускать changeSide метод, который мы определяем выше. Передавать не нужно updateMessage или любой из других методов – мы выбираем их из конструктора при создании экземпляра.

Вы можете представить, что это станет действительно полезным, если у нас много этих методов, с которыми нужно иметь дело. В моем случае мне нужно было позвонить .then(res => myFunction(res) после всего, что я пытался извлечь. Defining myFunction на экземпляре класса вместо того, чтобы передавать его каждой функции, сэкономил мне много кода.

Держа все в порядке

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

export default class ObjectManipulator {
  [...]

  colors = ['blue', 'red', 'orange', 'aquamarine', 'green', 'gray', 'magenta'];
};

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

Ссылки

Старые добрые документы Mozilla Class

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *