Создание приложения React с серверной частью Rails — часть 1
Поскольку я закончил всю свою курсовую работу в The Flatiron School, единственное, что осталось сделать до выпуска, — это создать приложение React с серверной частью API Rails. Просматривая разделы React и Redux Онлайн-программы веб-разработки, материал показался довольно простым. Мне не терпелось придумать идею проекта и реализовать эти новые библиотеки, которые я только что изучил. Мне пришла в голову идея создать приложение, похожее на Instagram, которое позволяет пользователям публиковать фотографии своих щенков и писать описание или подпись того, что их щенки делают на картинке. В этой записи блога я расскажу, как я создал API Rails, а затем реализовал React для внешнего интерфейса, а затем в следующей записи блога я расскажу, как я создал дизайн сайта.
Первым шагом было создание бэкенда. Я спорил, использовать ли команду Rails new или команду Rails new api для создания исходных файлов. Я решил использовать команду API Rails. Для этого я использовал следующую команду
rails new my_api_name --api
После того, как все файлы были созданы, я следовал следующей документации, чтобы настроить маршруты для API: http://guides.rubyonrails.org/api_app.html. Я использовал функцию маршрутизации пространства имен в config/routes.rb, чтобы поместить api/ перед всеми именами маршрутов.
//config/routes.rb Rails.application.routes.draw do namespace :api do resources :images end end
Следующим шагом было создание моих моделей, а затем моих контроллеров. Убедившись, что мой бэкэнд API был построен так, как я хотел, я добавил некоторые начальные данные. Моя модель была очень проста в создании. Я использовал генератор моделей Rails. Поскольку на данный момент у меня есть только модель изображения, мне не нужно беспокоиться о каких-либо ассоциациях. Команда, которую я использовал, была:
rails g model Image
Мой контроллер выглядит следующим образом:
class Api::ImagesController < ApplicationController def index @images = Image.all render json: @images end def create @image = Image.new(image_params) if @image.save render json: @image else render json: {errors: @image.errors}, status: 400 end end def update @image = Image.find(params[:id]) @image.update_attributes(image_params) render json: @image end private def image_params params.require(:image).permit(:imageURL, :name, :description) end end
Затем я следовал инструкциям в этой статье, чтобы подключить бэкэнд Rails к интерфейсу React. Эта статья дает хорошее введение в то, как использовать команду create-react-app. Мой совет по использованию этой статьи для соединения Rails и React — не торопитесь и внимательно читайте. Есть две ключевые вещи, которые вам нужно сделать после того, как вы выполнили инструкции в статье. Вам нужно установить драгоценный камень стойки cors.
gem install 'rack-cors'
Затем вам также нужно будет изменить файл config/initializers/cors.rb, чтобы он выглядел следующим образом:
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'localhost:3000' resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head] end end
Прежде чем я выполнил два вышеуказанных шага, у меня было много проблем с загрузкой моего приложения на сервер. Эти шаги устранили все ошибки Cors, которые я получал.
Теперь самое интересное — создание внешнего интерфейса приложения с помощью React. Когда мы ссылались на статью о подключении нашего API Rails к нашему приложению React, мы уже создали наше приложение React с помощью команды create react app.
Чтобы приступить к созданию внешнего интерфейса rails, я подключил свое приложение к хранилищу с помощью промежуточного программного обеспечения Provider из библиотеки redux. Я также импортировал create store, applyMiddleware и compose промежуточное ПО из библиотек Redux. Затем я создаю свой магазин с помощью функции createStore().
import React from 'react'; import ReactDOM from 'react-dom'; import App from './components/App'; import {Provider} from 'react-redux'; import {createStore, applyMiddleware, compose} from 'redux'; const store = createStore(rootReducer, compose(applyMiddleware(thunk), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())) ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
После настройки файла index.js я начал создавать компонент App.js. Этот компонент использует промежуточное ПО BrowserRouter и позволяет нам создать одностраничное приложение (SPA), используя маршруты для подключения всего.
import React, { Component } from 'react'; import Home from './Home' import Navbar from './Navbar' import {BrowserRouter as Router, Route} from 'react-router-dom'; import ImagesPage from '../containers/ImagesPage'; import '../App.css'; const App = () => <Router> <div> <header className="App-header"> <Navbar /> </header> <Route exact path="/" component={Home} /> <Route path="/images" component={ImagesPage} /> </div> </Router> export default App;
Оттуда я добавил контейнеры и компоненты, чтобы создать больше функциональности в самом приложении. Чтобы увидеть, как выглядели другие файлы, обратитесь к репозиторию github.
Одной из самых больших проблем, с которыми я столкнулся при работе с React, были редукторы и действия. В моем файле действий я использовал функцию JavaScript fetch() для извлечения данных из моего API Rails. В моем файле действий было определено 3 функции: getImages(), fetchImage() и addImage().
export function addImage (image) { return (dispatch) => { return fetch('http://localhost:3000/api/images', {method: 'post', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({image: image})}) .then(response => response.json()) .then(image => dispatch({type: 'ADD_IMAGE', image})) } } export function fetchImage (imageId) { return (dispatch) => { return fetch(`http://localhost:3000/api/images/${imageId}`) .then(response => response.json()) .then(imageId => dispatch({type: 'FETCH_IMAGE', imageId})) } } export function getImages () { return (dispatch) => { return fetch('http://localhost:3000/api/images', { headers : { 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(response => response.json()) .then(images => dispatch({type: 'GET_IMAGES', images})) } }
И мой файл редукторов:
export default (state = [], action) => { switch (action.type) { case 'ADD_IMAGE': return state.concat(action.image) case 'GET_IMAGES': return action.images case 'FETCH_IMAGE': return action.image default: return state; } };
После нескольких дней напряженной работы я успешно создал свой проект React с API серверной части Rails. В следующем разделе я расскажу, как я разработал свой проект.
Если у вас есть какие-либо вопросы о моем коде, пожалуйста, оставьте комментарий ниже.