Статьи

Как создать простой блог, используя React и GraphQL

Эта статья была спонсирована Cosmic JS . Спасибо за поддержку партнеров, которые делают возможным использование SitePoint.

В этом уроке я собираюсь показать вам, как создать простой блог с использованием React, GraphQL и Cosmic JS . Это будет самый быстрый и легкий блог, созданный на основе современных технологий. Давайте начнем.

TL; DR

Посмотреть демо
Установите блог Simple React на Cosmic JS
Посмотреть кодовую базу на GitHub

Космический JS

GraphQL

Начиная

Убедитесь, что на вашем компьютере установлены Node.js и NPM, в противном случае посетите веб-сайт Node.js, чтобы установить последнюю версию.

Давайте начнем с создания папки для нашего приложения. В вашем любимом терминале выполните следующие команды:

mkdir simple-react-blog
cd simple-react-blog

Теперь давайте добавим файл package.json, чтобы импортировать все наши зависимости для нашего приложения:

 vim package.json

Добавьте следующее в наш файл package.json:

 {
{
  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "next build; NODE_ENV=production node server.js"
  },
  "dependencies": {
    "axios": "^0.16.2",
    "express": "^4.16.2",
    "lodash": "^4.17.4",
    "next": "^4.0.3",
    "next-routes": "^1.1.0",
    "react": "^16.0.0",
    "react-dom": "^16.0.0"
  }
}

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

  1. Аксиос для нашего HTTP-клиента, основанного на обещаниях, для получения контента от Cosmic JS GraphQL API .
  2. Next.js как наша платформа React Universal.
  3. Следующие маршруты для динамических маршрутов.
  4. Express для нашего веб-приложения на стороне сервера.
  5. Реагировать на наш пользовательский интерфейс.

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

Запустите следующую команду, чтобы установить наши зависимости:

 npm i

Строим наш блог

Далее, давайте начнем создавать страницы нашего блога. Создайте папку страниц и добавьте файл index.js:

 vim index.js

и добавьте следующее в index.js:

 
import axios from 'axios'
import _ from 'lodash'
import Footer from './partials/footer'
import Header from './partials/header'
import helpers from '../helpers'
import config from '../config'

export default class extends React.Component {
  static async getInitialProps({ req }) {
    const query = `{
      objects(bucket_slug: "${config.bucket.slug}") {
        _id
        type_slug
        slug
        title
        metadata
        created_at
      }
    }`
    return await axios.post(`https://graphql.cosmicjs.com/v1`, { query })
    .then(function (response) {
      return {
        cosmic: {
          posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
          global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug')
        }
      }
    })
    .catch(function (error) {
      console.log(error)
    })
  }
  render() {
    if (!this.props.cosmic)
      return <div>Loading...</div>
    return (
      <div>
        <Header cosmic={ this.props.cosmic }/>
        <main className="container">
          {
            this.props.cosmic.posts &&
            this.props.cosmic.posts.map(post => {
              const friendly_date = helpers.friendlyDate(new Date(post.created_at))
              post.friendly_date = friendly_date.month + ' ' + friendly_date.date
              return (
                 <div className="card" data-href={`/${post.slug}`} key={post._id}>
                  {
                    post.metadata.hero.imgix_url &&
                    <a href={`/${post.slug}`} className="blog-post-hero blog-post-hero--short" style={{ backgroundImage: `url(${post.metadata.hero.imgix_url})`}}></a>
                  }
                  <div className="card-padding">
                    <h2 className="blog__title blog__title--small">
                      <a href={`/${post.slug}`}>{post.title}</a>
                    </h2>
                    <div className="blog__author">
                      <a href={`/author/${post.metadata.author.slug}`}>
                        <div className="blog__author-image" style={{ backgroundImage: `url(${post.metadata.author.metafields[0].imgix_url}?w=100)`}}></div>
                      </a>
                      <div className="blog__author-title">by <a href={`/author/${post.metadata.author.slug}`}>{post.metadata.author.title}</a> on {post.friendly_date}</div>
                      <div className="clearfix"></div>
                    </div>
                    <div className="blog__teaser droid" dangerouslySetInnerHTML={{__html: post.metadata.teaser}}></div>
                    <div className="blog__read-more">
                      <a href={`/${post.slug}`}>Read more...</a>
                    </div>
                  </div>
                </div>  
              )
            })
          }
        </main>
        <Footer />
      </div>
    )
  }
}

Здесь происходит несколько вещей:

  1. Мы импортируем наши основные модули: Axios, Lodash и другие помощники и компоненты.
  2. Мы добавляем некоторые партиалы: верхний и нижний колонтитулы, вы можете ссылаться на эти партиалы из базы кода на GitHub .
  3. Мы запрашиваем API Cosmic JS GraphQL, чтобы вернуть только то, что нам нужно: _id, type_slug, slug, title, metadata и creation_at.
  4. Мы устанавливаем основные реквизиты в нашем компоненте для cosmic И используйте lodash для разбора типов сообщений и глобальных объектов.
  5. Мы возвращаем данные массива постов и URL-адреса изображений в наш основной блог.

Один пост-запрос

Для нашего отдельного поста мы добавляем свойство post Сообщение найдено путем сопоставления query.slug и Object slug:

 
const gql_query = `{
  objects(bucket_slug: "${config.bucket.slug}") {
    type_slug
    slug
    title
    content
    metadata
    created_at
  }
}`
return await axios.post(`https://graphql.cosmicjs.com/v1`, { query: gql_query })
.then(function (response) {
  return {
    cosmic: {
      posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
      global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug'),
      post: _.find(response.data.data.objects, { slug: query.slug }),
    }
  }
})
.catch(function (error) {
  console.log(error)
})
}

Проверьте полный файл на GitHub .

Вывод

Это сокращенная версия блога Simple React, доступная для загрузки на странице Cosmic JS Apps . Полная кодовая база включает в себя один просмотр страницы поста, а также страницу, посвященную постам каждого автора. Просмотрите полную кодовую базу на GitHub и разверните это приложение в несколько кликов с панели управления Cosmic JS, установив приложение в корзину Cosmic JS.

Надеюсь, вам понравился этот урок, если у вас есть какие-либо вопросы, обращайтесь к нам в Twitter и присоединяйтесь к нашему сообществу в Slack .