Серия блогов React: Часть первая

Эта статья является первой в еженедельной серии статей о создании блога с помощью React и является основой для остальной части этой серии.

Серия блогов React

Часть первая: Создание веб-сайта с помощью React и Bulma
Часть вторая: Создание блога с помощью React и Contentful
Часть третья : Импортируйте свой канал Medium в React
Часть четвертая: Добавление Redux в блог React
Часть пятая: Замена Redux Thunks на Redux Sagas
Часть шестая: (В процессе) Написание модульного теста для блога React с Redux Sagas

Настраивать

Итак, давайте установим React

npm install -g create-react-app aaronklaser
cd aaronklaser
npm start

Затем давайте установим кое-что из того, что, как мы знаем, нам понадобится:

React Helmet
Bulma
Расширения Bulma
Moment
Стилизованные компоненты

npm install bulma bulma-extensions moment react-helmet styled-components --save

Настройте React для использования Sass

Это может быть не совсем необходимо, потому что мы в основном будем использовать стилизованные компоненты, но это значительно упростит импорт Bulma.

Теперь что касается сложной части, нам нужно настроить Sass, но я не хочу, чтобы вам приходилось извлекать из приложения create-react-app. Я последовал этому туториалу.

npm install --save node-sass-chokidar

Это создаст файлы .css из наших файлов .scss, от которых я не особо помешан, но пока давайте разберемся с этим. Мы хотим игнорировать наши файлы css в git, поэтому добавьте src/**/*.css в наш файл .gitignore.

Установите npm-run-all, чтобы мы могли включить нашу сборку scss в npm start

npm install --save npm-run-all

В package.json в сценариях npm добавьте build-css и watch-css, build-js и watch-js, а также измените build и начните использовать все наши новые scss-файлы.

"scripts": {
  "build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
  "watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive",
  "start-js": "react-scripts start",
  "start": "npm-run-all -p watch-css start-js",
  "build-js": "react-scripts build",
  "build": "npm-run-all build-css build-js",  
  "test": "react-scripts test --env=jsdom",
  "eject": "react-scripts eject"
}

ПРИМЕЧАНИЕ. Важно включить --include-path ./src --include-path ./node-modules как в build-css, так и в watch-css. Это позволяет нашему коду находить библиотеки, такие как Bulma, в нашей папке узловых модулей.

Добавление расширений Bulma и Bulma

Мы собираемся включить Bulma и любую конфигурацию Bulma в компонент индекса. Начните с переименования index.css в index.scss, затем перезапустите приложение, используя npm start

Если ничего не взорвалось, и ваш проект теперь включает index.scss и index.css, значит, все работает правильно.

Затем в вашем index.scss import bulma.

@import 'bulma/bulma';
@import 'bulma-extensions/extensions';

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

// 1. Import the initial variables
@import "bulma/sass/utilities/initial-variables";
@import "bulma/sass/utilities/functions";
// 2. Setup your Custom Colors
$purple: hsl(275,87%,45%);
$purple-invert: findColorInvert($purple);
// 3. Add new color variables to the color map.
@import "bulma/sass/utilities/derived-variables.sass";
$addColors: (
  "purple":($purple, $purple-invert),
);
$colors: map-merge($colors, $addColors);
@import 'bulma/bulma';
@import 'bulma-extensions/extensions';

Все должно запуститься, и ваши шрифты на стандартной домашней странице приложения create-react-app должны выглядеть иначе.

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

Базовый макет и заголовок

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

Фрактальная файловая структура

Впервые я нашел идею фрактальных файловых структур в статье на Hackernoon. В первый раз, когда я прочитал статью, идея была не очень ясна, но одна вещь всплыла у меня, и я думаю, что я ее понимаю. Я могу ошибаться, но, тем не менее, мой метод ОЧЕНЬ хорошо зарекомендовал себя в последние несколько месяцев. Это своего рода расширение шаблона ReDucks, за исключением того, что вы создаете своего рода значение ключа или структуру родительского дочернего объекта с вашими файлами.

src
|- index.js
|- App.js
|- app
   |- Layout.js
   |- layout
      |- Header.js
      |- Content.js
      |- Footer.js
|- User.js
|- user
   |- Profile.js
   |- PasswordReset.js
   |- Address.js
|- components
   |- SharedCompOne.js
   |- SharedCompTwo.js

Итак, вы можете видеть, что мы начинаем группировать наш код по модулям или функциям, но мы не создаем миллиард папок для каждого компонента. Вместо этого мы храним наши компоненты в их родительской папке, используя PascalCasing для каждого имени компонента и camelCasing для этой дочерней папки компонентов. Единственное реальное исключение - App.js технически является дочерним по отношению к index, но я не уверен, что это имеет значение 🤔.

Преимущество этого заключается в том, что мы можем ясно видеть, что Header, Content и Footer - все компоненты, используемые в компоненте Layout, который используется в компоненте App. Если бы структура полей была более плоской, например:

/* This is NOT fractal */
src
|- index.js
|- App.js
|- layout
   |- Layout.js
   |- Header.js
   |- Content.js
   |- Footer.js

Тогда у нас нет никаких реальных указаний на иерархию компонентов или на то, какие компоненты Layout.js даже используется, где, поскольку фрактальный шаблон показывает вам, кто именно использует какие компоненты и где. Это четкая родительская дочерняя структура, и макеты могут даже включать общую папку для компонентов, совместно используемых только внутри дочерних макетов.

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

src: {
  Index.js,
  App.js: {
    Layout.js: {
      Header.js
      Content.js
      Footer.js
    }
  }
  User.js: {
    Profile.js
    PasswordReset.js
    Address.js
  }
  components: {
    SharedCompOne.js
    SharedCompTwo.js
  }
}

Наш сайт начинает выглядеть как данные JSON… вроде как, но вы поняли. «Ключ» - это всегда компонентный файл .js. «Значение» - это, как всегда, папка с именем ключа, содержащая все дочерние компоненты.

Где это действительно начинает сиять, так это в вашем магазине, который я храню отдельно от моего презентационного слоя (приложения). Теперь мы можем начать структурировать наш магазин, как нашу структуру данных. Это ДЕЙСТВИТЕЛЬНО хорошо работает с NoSQL.

Мы поговорим об этом позже.

Начнем с приложения

  1. В корне создайте папку с именем app и создайте в ней файл с именем Layout.js
  2. В папке приложения создайте папку с именем layout
  3. В папке макета создайте 4 файла: Site.js, Header.js, Content.js и Footer.js.

App.js вызовет компонент Layout и позже включит наш Redux Store.

Layout.js будет содержать Site.js и Content.js, которые являются всего лишь оболочкой стилизованного компонента для сайт и контент, чтобы мы могли правильно настроить flexbox, а также компоненты Header.js и Footer.js.

Вот эти 5 файлов помещены в один Gist для нашего удобства.

Настроить маршрутизацию на некоторые страницы

npm install react-router-dom

Мы создаем простой веб-сайт / блог, поэтому будем использовать BrowserRouter. Есть и другой вариант, который вы можете изучить, но это не тема для этого;)

В корне нашего приложения в src/index.js мы собираемся обернуть приложение маршрутизатором.

import ReactDOM from 'react-dom'
import registerServiceWorker from './registerServiceWorker'
import { BrowserRouter as Router } from 'react-router-dom'
import App from './App'
import './index.css'
ReactDOM.render((
  <Router>
    <App />
  </Router>
), document.getElementById('root'))
registerServiceWorker()

Затем в папке приложения создадим две простые страницы Home.js и Blog.js.

import React from 'react'
const Home = () => (
  <p>This is the Home Page</p>
)
export default Home

а также

import React from 'react'
const Blog = () => (
  <p>This is the Blog Page</p>
)
export default Blog

Теперь, когда у нас есть несколько страниц для маршрутизации, давайте настроим компонент Router. На данный момент мы не будем пытаться делать с ним что-нибудь интересное, только простой и понятный Switch and Route.

В нашу папку макета добавляем новый файл call Router.js. Этот маршрутизатор будет находиться внутри содержимого нашего Layout.js файла. Здесь будут размещаться наши основные страницы верхнего уровня.

<Content>
  <Router />
</Content>

На страницах можно создавать дополнительные компоненты Routers, чтобы добавить более глубокую вложенную маршрутизацию. Наши соглашения об именах для тех, кто в будущем, будет их именем родительского компонента и Router. Например, BlogRouter.js или HomeRoute.js. Помните, что они будут жить в папке с названием blog.

В нашем компоненте маршрутизатора нам нужен компонент Switch и внутри него список или наши маршруты, использующие компонент Route.

import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './../Home'
import Blog from './../Blog'
const Router = () => (
  <Switch>
    <Route exact path='/' component={Home}/>
    <Route path='/blog' component={Blog}/>
  </Switch>
)
export default Router

И, наконец, давайте настроим наш заголовок для вызова этих маршрутов.

А пока давайте просто внесем изменения для двух страниц, для которых у нас есть маршруты. Мы собираемся изменить наши <a> в элементах навигации Blog и Logo Title.

<NavLink
  className="navbar-item"
  to="/"
  activeClassName="is-active"
>
  <img 
    style={{
      borderTopLeftRadius: '50%',
      borderTopRightRadius: '50%',
      borderBottomLeftRadius: '50%',
      borderBottomRightRadius: '50%',
      marginRight: 15
    }}
    src="https://media-exp2.licdn.com/mpr/mpr/shrinknp_400_400/AAEAAQAAAAAAAAU3AAAAJGE1MzYxNzYzLTE1NTUtNDEyYi04MzRjLTgzZjNkOGU0MGIzNg.jpg"
    width="30px" 
    alt="" 
  />
  <span>AaronKlaser.com</span>
</NavLink>

а также

<NavLink
  className="navbar-item"
  to="/blog"
  activeClassName="is-active"
>
  <span className="icon has-text-primary" style={{ marginRight: 5 }}
    <i className="fas fa-code"></i>
  </span>
  Code Blog
</NavLink>

Обратите внимание, что мы добавили activeClassName=”is-active”. Это потому, что это активный класс Bulma nav. Самое замечательное в NavLink - это то, что он всегда проверяет, на какой странице вы находитесь, и если ваш маршрут совпадает с NavLink to, он автоматически добавит is-active. Если вы не хотите добавлять активный класс, просто просто используйте компонент Link.

Заключение

Итак, это базовый фрейм приложения.

Рассмотрение

  • Настройте сайт React с помощью приложения create-react-app
  • Настройте React для сборки SassI
  • Установлена ​​Bulma
  • Мы узнали о фрактальных файловых структурах
  • Создал верстку сайта
  • Настроить маршрутизацию
  • Добавлены несколько страниц для перехода к

Далее - Создание блога с поддержкой React и Contentful

Еще не все! Я обновлю этот пост соответственно.