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
scottradcliff
March 16, 2018
Programming
0
190
Building API Driven React Applications
A look at some best practices for APIs in React apps
scottradcliff
March 16, 2018
Tweet
Share
More Decks by scottradcliff
See All by scottradcliff
Working Remote: What Works, What Doesn't, and Where to go From Here
scottradcliff
0
56
Teaching Programmers Through Empathy
scottradcliff
0
480
Other Decks in Programming
See All in Programming
Reading Rails 1.0 Source Code
okuramasafumi
0
230
Ruby×iOSアプリ開発 ~共に歩んだエコシステムの物語~
temoki
0
320
請來的 AI Agent 同事們在寫程式時,怎麼用 pytest 去除各種幻想與盲點
keitheis
0
120
もうちょっといいRubyプロファイラを作りたい (2025)
osyoyu
1
440
Android 16 × Jetpack Composeで縦書きテキストエディタを作ろう / Vertical Text Editor with Compose on Android 16
cc4966
2
230
AIと私たちの学習の変化を考える - Claude Codeの学習モードを例に
azukiazusa1
10
4.2k
testingを眺める
matumoto
1
140
アプリの "かわいい" を支えるアニメーションツールRiveについて
uetyo
0
270
AI Coding Agentのセキュリティリスク:PRの自己承認とメルカリの対策
s3h
0
230
MCPでVibe Working。そして、結局はContext Eng(略)/ Working with Vibe on MCP And Context Eng
rkaga
5
2.3k
MCPとデザインシステムに立脚したデザインと実装の融合
yukukotani
4
1.4k
Zendeskのチケットを Amazon Bedrockで 解析した
ryokosuge
3
310
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.9k
A designer walks into a library…
pauljervisheath
207
24k
Being A Developer After 40
akosma
90
590k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Rebuilding a faster, lazier Slack
samanthasiow
83
9.2k
Testing 201, or: Great Expectations
jmmastey
45
7.7k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Docker and Python
trallard
45
3.6k
Designing for Performance
lara
610
69k
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]