Created
March 26, 2018 06:36
-
-
Save nukotsuka/8719a7f26b673f8f4d63ecf568bcc9e3 to your computer and use it in GitHub Desktop.
Ruduxの書き方手順
This file contains hidden or 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 |
Author
Author
書く手順
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