Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Building API Driven React Applications
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
scottradcliff
March 16, 2018
Programming
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Building API Driven React Applications
A look at some best practices for APIs in React apps
scottradcliff
March 16, 2018
More Decks by scottradcliff
See All by scottradcliff
Working Remote: What Works, What Doesn't, and Where to go From Here
scottradcliff
0
64
Teaching Programmers Through Empathy
scottradcliff
0
510
Other Decks in Programming
See All in Programming
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
1
180
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
4
1.1k
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
270
act1-costs.pdf
sumedhbala
0
230
地域 SRE コミュニティ最前線 - ホンマでっかSRE勉強会
tk3fftk
0
230
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
220
Laravelで学ぶ Webアプリケーションチューニング入門/web_application_tuning_101
hanhan1978
3
450
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
170
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.8k
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.5k
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
120
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
570
Featured
See All Featured
Visualization
eitanlees
152
17k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Building Applications with DynamoDB
mza
96
7.1k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
Designing for Performance
lara
611
70k
The SEO identity crisis: Don't let AI make you average
varn
0
510
We Are The Robots
honzajavorek
0
280
Tell your own story through comics
letsgokoyo
1
990
Fireside Chat
paigeccino
42
4k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
How to train your dragon (web standard)
notwaldorf
97
6.7k
Transcript
API Driven React Applications
Security Speed Change API Design
Tools
mkdir react-talk-app cd react-talk-app mkdir server mkdir client
react-talk-app |—client |—server
create-react-app create-react-app client
client/ |-.gitignore |- README.md |- node_modules/ |- package.json |- public/
|- src/ |- yarn.lock
Components
import React, { Component } from ‘react'; import axios from
'axios'; import Product from ‘./Product’; class App extends Component { constructor() { super(); this.state = { products: []}; } componentWillMount() { axios.get(‘/api/v1/products’, headers: { Authorization: api_token}) .then(response => { this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) } render() { return ( <div> {this.state.products.map(product => { return <Product product={product} /> }) } </div> ); } } const compassModulesContainerElement = document.getElementById('compass-modules'); export default CompassModulesContainer; if (compassModulesContainerElement) { ReactDOM.render(<CompassModulesContainer />, compassModulesContainerElement); }
import React, { Component } from ‘react'; import axios from
'axios'; import Product from ‘./Product’; class App extends Component { constructor() { super(); this.state = { products: []}; } componentWillMount() { axios.get(‘/api/v1/products’) .then(response => { this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) } render() { return ( <div> {this.state.products.map(product => { return <Product product={product} /> }) } </div> ); } } const compassModulesContainerElement = document.getElementById('compass-modules'); export default CompassModulesContainer; if (compassModulesContainerElement) { ReactDOM.render(<CompassModulesContainer />, compassModulesContainerElement); }
import React, { Component } from ‘react'; import axios from
'axios'; import Product from ‘./Product’;
import React, { Component } from ‘react'; import axios from
'axios'; import Product from ‘./Product’; class App extends Component { constructor() { super(); this.state = { products: []}; } componentWillMount() { axios.get(‘/api/v1/products’, headers: { Authorization: api_token }) .then(response => { this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) } render() { return ( <div> {this.state.products.map(product => { return <Product product={product} /> }) } </div> ); } } const compassModulesContainerElement = document.getElementById('compass-modules'); export default CompassModulesContainer; if (compassModulesContainerElement) { ReactDOM.render(<CompassModulesContainer />, compassModulesContainerElement); }
class App extends Component { constructor() { super(); this.state =
{ products: []}; } componentWillMount() { axios.get(‘/api/v1/products’, headers: { Authorization: api_token }) .then(response => { this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) }
import React, { Component } from ‘react'; import axios from
'axios'; import Product from ‘./Product’; class App extends Component { constructor() { super(); this.state = { products: []}; } componentWillMount() { axios.get(‘/api/v1/products’, headers: { Authorization: api_token }) .then(response => { this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) } render() { return ( <div> {this.state.products.map(product => { return <Product product={product} /> }) } </div> ); } } const compassModulesContainerElement = document.getElementById('compass-modules'); export default CompassModulesContainer; if (compassModulesContainerElement) { ReactDOM.render(<CompassModulesContainer />, compassModulesContainerElement); }
render() { return ( <div> {this.state.products.map(product => { return <Product
product={product} /> }) } </div> ); } }
rails —api rails new server —api
server |- Gemfile |- Gemfile.lock |- README.md |- Rakefile |-
app/ |- bin/ |- config/ |- config.ru |- db …
Security
componentWillMount() { axios.get(‘/api/v1/products’, headers: { Authorization: api_token }) .then(response =>
{ this.setState({ products: response.data.products, }); }) .catch(error => alert(error)) }
class ApplicationController < ActionController::API def current_user Account.find_by(api_token: request.authorization) end end
module Api module V1 class ProductsController < ApplicationController def index
if current_user @products = Product.all render json: @products, status: 200 end end end end end
[ {id: 1, sku: “sku-1234”, price: 1200}, {id: 2, sku:
“sku-4321” price: 1300} ]
Active Model Serializers class ProductSerializer < ActiveModel::Serializer attributes :id, :name,
:sku, :price has_many :images end
Speed
module Api module V1 class ProductsController < ApplicationController def index
if current_user @products = Product.all render json: @products, include: :images, status: 200 end end end end end
[ {id: 1, sku: “sku-1234”, price: 1200, images: [ {id:1,
url: “someplace.jpg”}, {id: 2, url: “someotherplace.jpg”]}, {id: 2, sku: “sku-4321” price: 1300} ]
Change
Namespaces Rails.application.routes.draw do namespace :api do namespace :v1 do resources
:products end end end
Thanks! Scott Radcliff Freelance Software Developer scottradcliff.com @scottradcliff
[email protected]