Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactハンズオン 02 redux編 コード部分抜粋 / React Handson 02 redux (excerpt)

Reactハンズオン 02 redux編 コード部分抜粋 / React Handson 02 redux (excerpt)

Shunsuke Watanabe

September 07, 2018
Tweet

More Decks by Shunsuke Watanabe

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  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 => 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
  17. 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
  18. 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
  19. 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
  20. // 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
  21. 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
  22. 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
  23. 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. 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
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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