Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Building API Driven React Applications
Search
scottradcliff
March 16, 2018
Programming
220
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
69
Teaching Programmers Through Empathy
scottradcliff
0
520
Other Decks in Programming
See All in Programming
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
700
高専キャリア LT 発表内容
crysta1221
6
5.6k
AIの中の人になってみる
htkym
0
170
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
160
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
230
Family mrubyの進捗
kishima
1
110
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
140
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
430
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
自分的「カンファレンスの楽しみ方」
syumai
0
200
MIZARU@SPAJAM2026 第二回予選
1901drama
0
110
Can LLMs Replicate 4 Years of Compose Migration? Exploring the boundaries of automation with 279 XML files from a real product
makun
0
130
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
515
110k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
320
The Limits of Empathy - UXLibs8
cassininazir
1
650
What's in a price? How to price your products and services
michaelherold
247
13k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
230
GraphQLとの向き合い方2022年版
quramy
50
15k
For a Future-Friendly Web
brad_frost
183
10k
Agile that works and the tools we love
rasmusluckow
331
22k
HDC tutorial
michielstock
2
860
The agentic SEO stack - context over prompts
schlessera
0
920
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.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]