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
Reactハンズオン 02 redux編 コード部分抜粋 / React Handson 02...
Search
Shunsuke Watanabe
September 07, 2018
Programming
600
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Reactハンズオン 02 redux編 コード部分抜粋 / React Handson 02 redux (excerpt)
Shunsuke Watanabe
September 07, 2018
More Decks by Shunsuke Watanabe
See All by Shunsuke Watanabe
いますぐ {id: number;} をやめろ
craftgear
1
380
forループを越えて / beyond for loop
craftgear
0
590
Reactハンズオン 01 入門編 コード部分抜粋 / React Handson 01 components (excerpt)
craftgear
1
610
Reactハンズオン 01 入門編 コード部分抜粋 / React Handson 01 components (excerpt)
craftgear
0
730
Reactで作るDrupalサイト
craftgear
0
510
大阪Node学園 七時限目 「ゼロからはじめるnode.js」
craftgear
1
430
大阪Node学園 六時限目 「generator小咄」
craftgear
1
350
大阪Node学園四時限目 "This crazy testless world"
craftgear
1
350
Other Decks in Programming
See All in Programming
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
3k
【やさしく解説 設計編・中級 #4】ルールの寿命と、システムの年輪
panda728
PRO
2
170
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
150
霧の中の代数的エフェクト
funnyycat
1
430
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
150
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
230
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
390
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
110
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
190
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
3k
AIが無かった頃の素敵な出会いの話
codmoninc
1
220
Android CLI
fornewid
0
170
Featured
See All Featured
The Invisible Side of Design
smashingmag
301
52k
How to Talk to Developers About Accessibility
jct
2
430
Crafting Experiences
bethany
1
230
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
880
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
190
The Cult of Friendly URLs
andyhume
79
7k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
How to Think Like a Performance Engineer
csswizardry
28
2.7k
ラッコキーワード サービス紹介資料
rakko
1
4M
Are puppies a ranking factor?
jonoalderson
1
3.7k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
390
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.5k
Transcript
1 // src/index.js 2 3 import React from 'react'; 4
import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore } from 'redux'; 10 import { Provider } from 'react-redux'; 11 const store = createStore(/* error here */); 12 13 ReactDOM.render( 14 <Provider store={store}> 15 <App /> 16 </Provider>, 17 document.getElementById('root') 18 ); 19 registerServiceWorker(); 1
1 // src/reducers/helloWorld.js 2 3 const initState = { 4
greeting: '͜Μʹͪ', 5 to: 'ੈք', 6 }; 7 8 const helloWorld = (state = initState) => { 9 return state; 10 }; 11 12 export default helloWorld; 1 2 3 4 5 6 7 8 9 10 11 12 2
1 // src/index.js 2 3 import React from 'react'; 4
import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore } from 'redux'; 10 import { Provider } from 'react-redux'; 11 import helloWorld from './reducers/helloWorld'; 12 const store = createStore(helloWorld); 13 console.log('********* store.getState()', store.getState()); 14 15 ReactDOM.render( 16 <Provider store={store}> 17 <App /> 18 </Provider>, 19 document.getElementById('root') 20 ); 21 registerServiceWorker(); 3
1 // src/reducers/todo.js 2 3 const initState = { 4
items: [], 5 }; 6 7 const todo = (state = initState) => { 8 return state; 9 }; 10 11 export default todo; 1 2 3 4 5 6 7 8 9 10 11 4
1 // src/index.js 2 3 import React from 'react'; 4
import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore, combineReducers } from 'redux'; 10 import { Provider } from 'react-redux'; 11 import helloWorld from './reducers/helloWorld'; 12 import todo from './reducers/todo'; 13 const store = createStore( 14 combineReducers({ 15 helloWorld, 16 todo, 17 }) 18 ); 19 console.log('********* store.getState()', store.getState()); 20 21 ReactDOM.render( 22 <Provider store={store}> 23 <App /> 24 </Provider>, 25 document.getElementById('root') 26 ); 5
1 // src/reducers/index.js 2 3 import helloWorld from './helloWorld'; 4
import todo from './todo'; 5 6 export default { 7 helloWorld, 8 todo, 9 }; 1 // src/index.js 2 3 import React from 'react'; 4 import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore, combineReducers } from 'redux'; 10 import { Provider } from 'react-redux'; 11 import reducers from './reducers'; 12 const store = createStore(combineReducers(reducers)); 13 14 ReactDOM.render( 1 2 3 4 5 6 7 8 9 6
1 // src/components/HelloWorld.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 6 const styles = { 7 helloWorld: { 8 color: 'orange', 9 backgroundColor: 'black', 10 }, 11 }; 12 13 const HelloWorld = ({ greeting, to }) => ( 14 <h1 style={styles.helloWorld}> 15 {greeting} {to} 16 </h1> 17 ); 18 19 export default connect()(HelloWorld); 7
1 // src/components/HelloWorld.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 …… 12 13 const HelloWorld = ({ greeting, to }) => ( 14 <h1 style={styles.helloWorld}> 15 {greeting} {to} 16 </h1> 17 ); 18 19 const mapStateToProps = state => ({ 20 greeting: state.helloWorld.greeting, 21 to: state.helloWorld.to, 22 }); 23 24 export default connect(mapStateToProps)(HelloWorld); 8
1 // src/components/HelloWorld.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 …… 12 13 const action = { 14 type: 'UPDATE_GREETING', 15 payload: 'Hola!', 16 }; 17 18 const HelloWorld = ({ greeting, to, dispatch }) => ( 19 <div> 20 <h1 style={styles.helloWorld}> 21 {greeting} {to} 22 </h1> 23 <button onClick={() => dispatch(action)}>dispatch</button> 24 </div> 25 ); 26 27 const mapStateToProps = state => ({ 28 greeting: state.helloWorld.greeting, 29 to: state.helloWorld.to, 30 }); 9
1 // src/reducers/helloWorld.js 2 3 const initState = { 4
greeting: '͜Μʹͪ', 5 to: 'ੈք', 6 }; 7 8 const helloWorld = (state = initState, action) => { 9 const { type, payload } = action; 10 11 switch (type) { 12 case 'UPDATE_GREETING': { 13 return { 14 ...state, 15 greeting: payload, 16 }; 17 } 18 default: 19 return state; 20 } 21 }; 22 23 export default helloWorld; 10
1 const obj = { 2 a: 'aaa', 3 b:
'bbb', 4 }; 5 6 const copy = { 7 ...obj, 8 }; 9 10 const update = { 11 ...obj, 12 a: '͋͋͋', 13 }; 14 15 const add = { 16 ...obj, 17 c: 'ccc', 18 }; 19 20 console.log('obj is ', obj); 21 console.log('copy is ', copy); 22 console.log('update is ', update); 23 console.log('add is ', add); 11
1 // src/actins/index.js 2 3 export const UPDATE_GREETING = 'UPDATE_GREETING';
4 export const updateGreeting = greeting => ({ 5 type: UPDATE_GREETING, 6 payload: greeting, 7 }); 1 // src/reducers/helloWorld.js 2 3 import { UPDATE_GREETING } from '../actions'; 4 …… 10 const helloWorld = (state = initState, action) => { 11 const { type, payload } = action; 12 13 switch (type) { 14 case UPDATE_GREETING: { 15 return { 16 ...state, 17 greeting: payload, 18 }; 19 } 20 default: 1 2 3 4 5 6 7 12
1 // src/components/HelloWorld.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 import { updateGreeting } from '../actions'; …… 13 14 const action = updateGreeting('Guten tag'); 15 16 const HelloWorld = ({ greeting, to, dispatch }) => ( 17 <div> 18 <h1 style={styles.helloWorld}> 19 {greeting} {to} 20 </h1> 21 <button onClick={() => dispatch(action)}>dispatch</button> 22 </div> 23 ); 24 25 const mapStateToProps = state => ({ 26 greeting: state.helloWorld.greeting, 27 to: state.helloWorld.to, 28 }); 29 30 export default connect(mapStateToProps)(HelloWorld); 13
1 // src/index.js 2 3 import React from 'react'; 4
import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore, combineReducers, applyMiddleware } from 'redux'; 10 import { Provider } from 'react-redux'; 11 import thunk from 'redux-thunk'; 12 import reducers from './reducers'; 13 const store = createStore(combineReducers(reducers), applyMiddleware(thunk)); 14 15 ReactDOM.render( 16 <Provider store={store}> 17 <App /> 18 </Provider>, 19 document.getElementById('root') 20 ); 21 registerServiceWorker(); 14
1 // src/actins/index.js 2 3 export const UPDATE_GREETING = 'UPDATE_GREETING';
4 export const updateGreeting = greeting => dispatch => { 5 setTimout(() => { 6 dispatch({ 7 type: UPDATE_GREETING, 8 payload: greeting, 9 }); 10 }, 1000); 11 }; 15
1 // src/actins/index.js 2 3 import request from 'request-promise-native'; 4
5 export const UPDATE_GREETING = 'UPDATE_GREETING'; 6 export const updateGreeting = greeting => dispatch => { 7 request({ 8 uri: 'http://localhost:3000/greeting.json', 9 json: true, 10 }).then(res => { 11 dispatch({ 12 type: UPDATE_GREETING, 13 payload: res.data, 14 }); 15 }); 16 }; 16
1 // src/actins/index.js 2 3 import request from 'request-promise-native'; 4
5 export const UPDATE_GREETING = 'UPDATE_GREETING'; 6 export const updateGreeting = greeting => async dispatch => { 7 const res = await request({ 8 uri: 'http://localhost:3000/greeting.json', 9 json: true, 10 }); 11 dispatch({ 12 type: UPDATE_GREETING, 13 payload: res.data, 14 }); 15 }; 17
1 // src/index.js 2 3 import React from 'react'; 4
import ReactDOM from 'react-dom'; 5 import './index.css'; 6 import App from './App'; 7 import registerServiceWorker from './registerServiceWorker'; 8 9 import { createStore, combineReducers, applyMiddleware } from 'redux'; 10 import { Provider } from 'react-redux'; 11 import thunk from 'redux-thunk'; 12 import { composeWithDevTools } from 'redux-devtools-extension'; 13 import reducers from './reducers'; 14 const store = createStore( 15 combineReducers(reducers), 16 composeWithDevTools(applyMiddleware(thunk)) 17 ); 18 19 ReactDOM.render( 20 <Provider store={store}> 21 <App /> 22 </Provider>, 23 document.getElementById('root') 24 ); 18
1 // src/actins/todo.js 2 3 import request from 'request-promise-native'; 4
5 export const FETCH_TODOS_PENDING = 'FETCH_TODOS_PENDING'; 6 export const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS'; 7 export const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE'; 8 export default () => async dispatch => { 9 dispatch({ type: FETCH_TODOS_PENDING }); 10 try { 11 const res = await request({ 12 uri: 'http://localhost:3000/dummy_todos.json', 13 json: true, 14 }); 15 16 dispatch({ 17 type: FETCH_TODOS_SUCCESS, 18 payload: res.data, 19 }); 20 } catch (e) { 21 dispatch({ type: FETCH_TODOS_FAILURE, error: e }); 22 } 23 }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 19
// src/reducers/todo.js import { FETCH_TODOS_PENDING, FETCH_TODOS_SUCCESS, FETCH_TODOS_FAILURE } from '../actions/todo';
const initState = { items: [], error: null, loading: false, }; export default (state = initState, action) => { const { type, payload, error } = action; switch (type) { case FETCH_TODOS_PENDING: return { ...state, loading: true }; case FETCH_TODOS_SUCCESS: return { ...state, items: payload, loading: false, }; case FETCH_TODOS_FAILURE: return { ...state, error, loading: false, }; default: return state; } }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 20
1 // src/App.js 2 3 import React, { Component }
from 'react'; 4 5 import HelloWorld from './components/HelloWorld'; 6 import TodoList from './components/TodoList'; 7 8 import './App.css'; 9 10 class App extends Component { 11 constructor(props) { 12 super(props); 13 } 14 15 render() { 16 return ( 17 <div className="App"> 18 <HelloWorld /> 19 <TodoList /> 20 </div> 21 ); 22 } 23 } 24 25 export default App; 21
1 // src/components/TodoList/index.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 import TodoItem, { TodoHeader } from './TodoItem'; 6 7 const styles = { 8 list: { 9 width: '100%', 10 display: 'grid', 11 justifyItems: 'center', 12 }, 13 }; 14 15 const TodoList = ({ todos }) => ( 16 <div style={styles.list}> 17 <TodoHeader /> 18 {todos.map(todo => <TodoItem key={todo.id} {...todo} />)} 19 </div> 20 ); 21 22 const mapStateToProps = state => ({ 23 todos: state.todo.items 24 }) 25 26 export default connect(mapStateToProps)(TodoList) 22
1 // src/components/HelloWorld.js 2 3 import React from 'react'; 4
import { connect } from 'react-redux'; 5 import fetchTodos from '../actions/todo'; …… 13 14 const HelloWorld = ({ greeting, to, dispatch }) => ( 15 <div> 16 <h1 style={styles.helloWorld}> 17 {greeting} {to} 18 </h1> 19 <button onClick={() => dispatch(fetchTodos())}>fetch todos</ button> 20 </div> 21 ); 22 23 const mapStateToProps = state => ({ 24 greeting: state.helloWorld.greeting, 25 to: state.helloWorld.to, 26 }); 27 28 export default connect(mapStateToProps)(HelloWorld); 23
24 1 // src/actions/todo.js 2 3 export const FETCH_TODOS_PENDING =
'FETCH_TODOS_PENDING'; 4 export const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS'; 5 export const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE'; 6 7 export default () => ({ 8 type: FETCH_TODOS_PENDING, 9 }); npm install --save redux-observable rxjs 24
1 // src/epics/todo.js 2 3 import { ofType } from
'redux-observable'; 4 import { switchMap, map, catchError, tap } from 'rxjs/operators'; 5 import request from 'request-promise-native'; 6 export default action$ => 7 action$.pipe( 8 ofType('FETCH_TODOS_PENDING'), 9 tap(action => console.log('******** action is ', action)), 10 switchMap(action => 11 request({ 12 uri: 'http://localhost:3000/dummy_todos.json', 13 json: true, 14 }) 15 .then(response => ({ 16 type: 'FETCH_TODOS_SUCCESS', 17 payload: response.data, 18 })) 19 .catch(e => ({ type: 'FETCH_TODOS_FAILURE', error: e })) 20 ) 21 ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 25
1 // src/index.js …… 12 import reducers from './reducers'; 13
import { combineEpics, createEpicMiddleware } from 'redux-observable'; 14 import fetchTodoEpic from './epics/todo'; 15 const rootEpic = combineEpics(fetchTodoEpic); 16 const epicMiddleware = createEpicMiddleware(); 17 const store = createStore( 18 combineReducers(reducers), 19 composeWithDevTools(applyMiddleware(epicMiddleware)) 20 ); 21 epicMiddleware.run(rootEpic); // applyMiddlewareͷ͋ͱʹ͓͘͜ͱ 22 23 ReactDOM.render( 24 <Provider store={store}> 25 <App /> 26 </Provider>, 27 document.getElementById('root') 28 ); 29 registerServiceWorker(); 26
1 // src/epics/todo.js 2 3 import { ofType } from
'redux-observable'; 4 import { of } from 'rxjs'; 5 import { switchMap, map, catchError, tap, delay } from 'rxjs/ operators'; 6 import { ajax } from 'rxjs/ajax'; 7 export default action$ => 8 action$.pipe( 9 ofType('FETCH_TODOS_PENDING'), 10 switchMap(action => 11 ajax.getJSON('http://localhost:3000/dummy_todos.json').pipe( 12 map(response => { 13 return { 14 type: 'FETCH_TODOS_SUCCESS', 15 payload: response.data, 16 }; 17 }), 18 catchError(error => 19 of({ 20 type: 'FETCH_TODOS_FAILURE', 21 payload: error.message, 22 error: true, 23 }) 24 ) 25 ) 26 ) 27 ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 27
1 // src/middlewares/now.js 2 3 export default store => next
=> action => { 4 const actionWithNow = { 5 ...action, 6 now: Date.now(), 7 }; 8 9 next(actionWithNow); 10 }; 1 // src/index.js …… 14 import now from './middlewares/now'; 15 const store = createStore( 16 combineReducers(reducers), 17 composeWithDevTools(applyMiddleware(thunk, now)) 18 ); 19 …… 28
1 // src/middlewares/log.js 2 3 export default store => next
=> action => { 4 console.info(`TYPE: ${action.type}, PAYLOAD: $ {action.payload}`); 5 next(action); 6 }; 1 // src/index.js …… 14 import now from './middlewares/now'; 15 import log from './middlewares/log'; 16 const store = createStore( 17 combineReducers(reducers), 18 composeWithDevTools(applyMiddleware(thunk, now, log)) 19 ); …… 29