Эта статья предполагает предварительное знание react.js. В конце этой статьи я надеюсь, что вы узнаете кое-что о том, как уберечь доменную (бизнес-логику) от реагирующего компонента и, следовательно, сделать их более тестируемыми и легкими в рассуждении. Запустите свой любимый редактор кода и приступим.

В этой статье вы узнаете, как создать простое, но полезное react.js приложение. Ниже приводится сводка функций, которые мы будем реализовывать:

  1. Составьте список карточек на основе json данных и реализуйте разбиение на страницы, показывая 12 элементов на странице.
  2. Применяйте к карточкам другой цвет фона в зависимости от значения поля (color_id).
  3. Реализуйте фильтрацию по паре полей.

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

Настройка среды разработки

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

Это те, которые я считаю полезными для развития моей реакции. Откройте свой терминал и выполните следующие команды:

npx create-react-app card-game 
cd card-game 
npm start

Чтобы получить отличный опыт разработки, давайте настроим Eslint и Prettier. Планируется использовать Eslint для форматирования нашего javaScript и Prettier для всего остального. Откройте свой терминал и выполните следующие команды, чтобы установить пару зависимостей разработки.

npm i -D eslint-config-prettier eslint-plugin-prettier prettier

Создайте .eslintrc и добавьте следующие строки

{ 
  "extends": ["react-app", "plugin:prettier/recommended"] 
}

Добавьте следующее в настройки пользователя VSCode

{
  "editor.formatOnSave": true,
  "[javascript]": {
    "editor.formatOnSave": false
  },
  "eslint.autoFixOnSave": true,
  "eslint.alwaysShowStatus": true,
  "prettier.disableLanguages": [
    "js"
  ]
}

Использование "prettier.disableLanguages": [ "js" ] предотвратит запуск prettier с js файлами, поскольку ESLint получил нашу поддержку. Ура!!

Приступим к кодированию

Начнем с уборки. Удалить App.css, App.test.js, logo.svg, serviceWorker.js.

Чтобы не терять много времени, давайте добавим наш образец json' файла, вызовем его Ajax и просто отобразим. В каталоге public создайте каталог data и добавьте test.json.

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

src/
|
|– components/
|   |– Filter.js
|   |– Pagination.js
|   |– PaginationItem.js
|
|
|– model/
|   |– constants.js
|   |– Game.js
|
|
|– api/
|   |– api.js

Обновите api.js, используя приведенный ниже код

export async function getGames() {
    return await gamesData;
}
async function loadData() {
    try {
      const data = await (await fetch("/data/test.json")).json();
      return data;
    } catch (e) {
      console.error(e);
    }
 }
 /* This is to ensure that a one time call is made for the games data */
 const gamesData = loadData();

Теперь обновите App.js, как показано ниже.

import React, { Component } from "react";
import { getGames } from "./api/api";
class App extends Component {
  state = {
    games: []
  };
  componentDidMount() {
    this.loadGames();
  }
  loadGames = async () => {
    try {
      const games = await getGames();
      this.setState({ games });
    } catch (e) {
      console.error(e);
    }
  };
  render() {
    const { games } = this.state;
    return (
      <div className="App">
        <pre>{JSON.stringify(games, null, 4)}</pre>
      </div>
    );
  }
}
export default App;

Это настолько просто, насколько это возможно. После выполнения предыдущей команды npm start ваш браузер должен отображать json тестовые данные. Как часто разработчики JavaScript хотят, чтобы все json API использовали верблюжий регистр для ключей !. Например, мы предпочитаем firstName, а не first_name. Младенцы некоторые линтеры будут кричать на вас за то, что вы поступаете иначе. Давайте исправим это сейчас, добавив constants.js и Game.js в каталог модели.

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

Каждый объект в test.json будет отображен для возврата экземпляра Game. Давайте не будем обновлять наш api.js, чтобы отразить изменения. В apiljs обновите строку return data; на return data.map(game => new Game(game));. Не забудьте импортировать Game.js

Теперь давайте обновим App.js, чтобы каждый элемент отображался в виде карточки. Добавьте метод renderCards, а также обновите метод render, как показано ниже:

renderCards() {
    const { games } = this.state;
    if (!games.length) {
      return <div>No Items Found...</div>;
    }
    return games.map(({ id, color }) => (
      <div
        key={id}
        className="games__item"
        style={{ backgroundColor: color }}
      />
    ));
  }
render() {
    return (
      <div className="container">
        <div className="games">{this.renderCards()}</div>
      </div>
    );
  }

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

Теперь приступим к добавлению нумерации страниц. Добавьте / обновите Pagination.js и PaginationItem.js с помощью следующего кода:

Не уверен насчет вас, но я считаю Array.from({ length: someNumber}, mapFn) интересным способом создания последовательности чисел и сопоставления с ней. Чтобы выделить текущую страницу, я также передаю selected prop. Ниже приведен код для PaginationItem.js.

Не забудьте установить пакет classnames с помощью следующей команды npm i -S classnames. Чтобы полностью интегрировать разбиение на страницы, обновим api.js и App.js

Я всегда стараюсь как можно больше освободить свой компонент реакции от логики предметной области, отсюда и причина добавления удобного свойства total в метод getGames. Уф 😅, давайте добавим последнее обновление для App.js и закончим.

Обратите внимание, что size определяется как свойство класса, а не в состоянии on, поскольку он не имеет ничего общего с дальнейшим повторным рендерингом компонента реакции. Назовем это накруткой. Если вы дочитали до этого места, я надеюсь, что вы нашли эту статью полезной. Скоро выложу финальную часть (с фильтрацией). Большое спасибо за чтение и, пожалуйста, не стесняйтесь делиться и комментировать.

Ссылка GitHub на исходный код: