(Перевод) Основы шаблона проектирования компонентов React

внешний интерфейс Шаблоны проектирования React.js
(Перевод) Основы шаблона проектирования компонентов React

Оригинальная ссылка:React Component Patterns

автор:Gustavo Matheus

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

С сохранением состояния против без гражданства

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

Ниже приведеннет статусаизButtonКомпонент, поведение которого полностью определяется реквизитами, переданными в:

const Button = props => 
  <button onClick={props.onClick}>
    {props.text}
  </button>

Ниже приведенсостояниекомпонент (используя вышеуказанныйнет статусакомпоненты):

class ButtonCounter extends React.Component {
  constructor() {
    super();
    this.state = { clicks: 0 };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState({ clicks: ++this.state.clicks });
  }

  render() {
    return (
      <Button
        onClick={this.handleClick}
        text={`You've clicked me ${this.state.clicks} times !`}
      />
    )
  }
}

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

Контейнер против презентационных компонентов

При взаимодействии с внешними данными мы можем разделить компоненты на две категории:

  • компонент контейнера: в основном отвечает за взаимодействие (общение) с внешними данными, такими какReduxи так далее для привязки данных и т.д.
  • Компоненты дисплея: визуализирует на основе собственного состояния и свойств, полученных от родительского компонента, и не взаимодействует напрямую с внешними источниками данных.

давайте посмотрим на одинэкспонатКомпоненты:

const UserList = props =>
  <ul>
    {props.users.map(u => (
      <li>{u.name} - {u.age} years old</li>
    ))}
  </ul>

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

class UserListContainer extends React.Component {
  constructor() {
    super()
    this.state = { users: [] }
  }

  componentDidMount() {
    fetchUsers(users => this.setState({ users }));
  }

  render() {
    return <UserList users={this.state.users} />
  }
}

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

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

Компоненты высшего порядка (HOC) пригодятся, когда вы хотите повторно использовать логику компонента. Компонент высшего порядка — это функция JavaScript, которая принимает компонент React в качестве параметра и возвращает новый компонент.

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

function makeToggleable(Clickable) {
  return class extends React.Component {
    constructor() {
      super();
      this.toggle = this.toggle.bind(this);
      this.state = { show: false };
    }

    toggle() {
      this.setState({ show: !this.state.show });
    }

    render() {
      return (
        <div>
          <Clickable
            {...this.props}
            onClick={this.toggle}
          />
          {this.state.show && this.props.children}
        </div>
      );
    }
  }
}

Таким образом, мы можем использовать синтаксис декоратора JavaScript, чтобы применить нашу логику кToggleableMenuКомпоненты:

@makeToggleable
class ToggleableMenu extends React.Component {
  render() {
    return (
      <div onClick={this.props.onClick}>
        <h1>{this.props.title}</h1>
      </div>
    );
  }
}

Теперь мы можем поместить любое содержимое подменю вToggleableMenuВ компоненте:

class Menu extends React.Component {
  render() {
    return (
      <div>
        <ToggleableMenu title="First Menu">
          <p>Some content</p>
        </ToggleableMenu>
        <ToggleableMenu title="Second Menu">
          <p>Another content</p>
        </ToggleableMenu>
        <ToggleableMenu title="Third Menu">
          <p>More content</p>
        </ToggleableMenu>
      </div>
    );
  }
}

когда вы используетеReduxизconnect,илиReact RouterизwithRouterфункция, вы используете компонент более высокого порядка!

Рендеринг обратного вызова (рендеринг обратных вызовов)

Помимо компонентов высокого порядка,визуализировать обратный вызов— это еще один шаблон проектирования, делающий компоненты повторно используемыми.визуализировать обратный вызовЯдром компонента является дочерний компонент (или дочерний узел, т.е.props.children), не кReact Componentпредоставляется, но в виде функции обратного вызова. с вышеуказаннымHOCкомпонент в качестве примера, мы передаемоказыватьМетод обратного вызова переписывается следующим образом:

class Toggleable extends React.Component {
  constructor() {
    super();
    this.toggle = this.toggle.bind(this);
    this.state = { show: false }
  }

  toggle() {
    this.setState({ show: !this.state.show });
  }

  render() {
    return this.props.children(this.state.show, this.toggle)
  }
}

Теперь мы можем передать функцию обратного вызова вToggleableКомпоненты как дочерние узлы. Реализуем предыдущий на новый ладHOCкомпонентыToggleableMenu:

const ToggleableMenu = props => (
  <Toggleable>
    {(show, onClick) => (
      <div>
        <div onClick={onClick}>
          <h1>{props.title}</h1>
        </div>
        { show && props.children }
      </div>
    )}
  </Toggleable>
)

И наш новыйMenuКомпонент реализован следующим образом:

class Menu extends React.Component {
  render() {
    return (
      <div>
        <ToggleableMenu title="First Menu">
          <p>Some content</p>
        </ToggleableMenu>
        <ToggleableMenu title="Second Menu">
          <p>Another content</p>
        </ToggleableMenu>
        <ToggleableMenu title="Third Menu">
          <p>More content</p>
        </ToggleableMenu>
      </div>
    );
  }
}

да, вы правильно прочитали, новыйMenuКомпоненты те же, что и раньшеHOCВыкройка реализована точно так же!

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

понять больше

Некоторые из приведенных выше примеров — это лишь основы шаблонов проектирования React. Если вы хотите углубиться в тему шаблонов проектирования React, вот несколько действительно хороших учебных материалов, на которые стоит обратить внимание:


Обратите внимание на публичный аккаунт WeChat: KnownsecFED, получайте больше качественной галантереи по коду!