Created
March 26, 2018 06:36
-
-
Save nukotsuka/8719a7f26b673f8f4d63ecf568bcc9e3 to your computer and use it in GitHub Desktop.
Ruduxの書き方手順
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Redux |
書く手順
Reducer
src/reducers/tasks.js
const initialState = {
task: '',
tasks: []
};
export default function tasksReducer(state = initialState, action) {
switch (action.type) {
case 'INPUT_TASK':
return {
...state,
task: action.payload.task
};
case 'ADD_TASK':
return {
...state,
tasks: state.tasks.concat([action.payload.task])
};
default:
return state;
}
}
initialState
でStoreに保存するStateを決める。- Reducerが多く、分割する場合は
combineReducer
を用いる。(createStore.jsでまとまる場合は不要(?))
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
messageModal,
aService,
errorMessage,
router
});
export default rootReducer;
Store
src/createStore.js
import {
createStore as reduxCreateStore,
combineReducers,
applyMiddleware
} from 'redux'
import {routerReducer, routerMiddleware} from 'react-router-redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import tasksReducer from '../reducers/tasks'
export default function createStore(history) {
return reduxCreateStore(
combineReducers({
tasks: tasksReducer,
router: routerReducer,
}),
applyMiddleware(
routerMiddleware(history),
logger,
thunk
)
);
}
- ReducerとMiddlewarをここでStoreに紐づける。
combineReducer
では分割された子Reducer名と同じキーのstate
が使用できる。(ex. state.tasks, state.router)- Redux DevToolsを用いる場合は以下。
import {
createStore as reduxCreateStore,
combineReducers,
applyMiddleware,
compose
} from 'redux'
import {routerReducer, routerMiddleware} from 'react-router-redux'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import userReducer from "./reducers/userReducer";
import countReducer from "./reducers/countReducer";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default function createStore(history) {
return reduxCreateStore(
combineReducers({
user: userReducer,
count: countReducer,
router: routerReducer,
}),
composeEnhancers(
applyMiddleware(
routerMiddleware(history),
logger,
thunk
)
)
);
}
Root
src/ index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Route} from 'react-router-dom'
import {Provider} from 'react-redux'
import {ConnectedRouter} from 'react-router-redux'
import createBrowserHistory from 'history/createBrowserHistory'
import createStore from './store/index'
import TodoApp from './containers/TodoApp'
import Error from './components/Error'
const history = createBrowserHistory();
const store = createStore(history);
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Route exact path="/" component={TodoApp}/>
<Route exact path="/error" component={Error}/>
</div>
</ConnectedRouter>
</Provider>,
document.getElementById('root')
);
Provider
でComponentにstore
を紐づける。ConnectedRouter
でComponentにhistory
を紐づける。Route
でRoutingを行う。- ここにはないが、
react-router-dom
のLink
を用いてページ遷移する。
import {Link} from 'react-router-dom'
<Link to="/error">エラー</Link>
- または、
react-router-dom
のSwitch
と、
import {Route, Switch} from 'react-router-dom'
<Switch>
<Route exact path="/" component={TodoApp}/>
<Route exact path="/error" component={Error}/>
<Switch/>
react-router-redux
のpush
を用いてページ遷移する。
import {push} from 'react-router-redux'
dispatch(push('/error'))
ActionCreater
src/actions/taks.js
export const inputTask = (task) => ({
type: 'INPUT_TASK',
payload: {
task
}
});
export const addTask = (task) => ({
type: 'ADD_TASK',
payload: {
task
}
});
flux-standard-action規約
{
type: FOO_TYPE, // must
payload: {object}, // optional
meta: {object}, // optional
error: false, true, undefined, null, ... // optional
}
thunk
を用いた非同期なActionCreater
export const signIn = (name, email, password) => ({
type: 'SIGN_IN',
payload: {name, email, password}
});
export const asyncSignIn = (email, password) => {
return dispatch => {
request
.get(url)
.set('Content-Type', 'application/json')
.set('Access-Control-Allow-Origin', '*')
.query({email: email, password: password})
.end(function (err, res) {
if (err) {
console.log(err);
} else {
console.log(res);
dispatch(signIn(res.body.name, res.body.email, res.body.password));
dispatch(push('/count'));
}
});
};
};
thunk
を用いた複数のActionCreaterをまとめたActionCreater
export const inputEmail = (email) => ({
type: 'INPUT_EMAIL',
payload: {email}
});
export const inputPassword = (password) => ({
type: 'INPUT_PASSWORD',
payload: {password}
});
export const inputAction = (email, password) => {
return (dispatch) => {
dispatch(inputEmail(email));
dispatch(inputPassword(password));
};
};
Container
src/containers/Ranking.js
import {connect} from 'react-redux'
import {push} from 'react-router-redux'
import TodoApp from '../components/TodoApp'
import {inputTask, addTask} from "../actions/tasks";
const mapStateToProps = ({tasks}) => {
return {
task: tasks.task,
tasks: tasks.tasks
};
};
const mapDispatchToProps = (dispatch) => ({
addTask: task => dispatch(addTask(task)),
inputTask: task => dispatch(inputTask(task)),
redirectToError: () => dispatch(push('/error'))
});
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
mapStateToProps
でstate
を受け取り、Componentに渡すものを決める。state.hoge
などはhoge
で扱える。mapDispatchToProps
でdispatch
を受け取り、importしたActionCreaterを用いてComponentに渡すメソッドを決める。connect
でComponentにmapStateToProps
とmapDispatchToProps
を渡す。
Component
src/component/TodoApp.js
import React from 'react'
import PropTypes from 'prop-types'
const TodoApp = ({task, tasks, inputTask, addTask, redirectToError}) => (
<div>
<input type="text" onChange={(e) => inputTask(e.target.value)}/>
<input type="button" value="add" onClick={() => addTask(task)}/>
<ul>
{
tasks.map((item, i) => {
return (
<li key={i}>{item}</li>
);
})
}
</ul>
<button onClick={() => redirectToError()}>エラーページへ</button>
</div>
)
TodoApp.propTypes = {
task: PropTypes.string.isRequired,
tasks: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
inputTask: PropTypes.func.isRequired,
addTask: PropTypes.func.isRequired,
redirectToError: PropTypes.func.isRequired
}
export default TodoApp
- Containerから渡された
mapStateToProps
,mapDispatchToProps
の中身を引数に取る。 PropTypes
を用いてpropTypes
を設定する。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
インストール
Redux
Router
Midleware
PropTypes