Reduxの基本的な使い方【Reactアプリで状態管理をする】
先日Reactでアプリを作成しました。
駅名、料理のジャンル、個室の有無、支払い方法を選択し、お店の検索ができるグルメアプリです。
駅名などの入力内容を保存する際にReduxを使用しています。
今回はこのアプリを用いて、Reduxの基本的な使い方をまとめます。
記事の内容
- Reduxとは
- 導入
- state
- Action
- Reducer
- Store
- mapStateToProps
- mapDispatchToProps
- Storeにアクセスする
スポンサードサーチ
Reduxとは
Reduxはアプリの状態を管理するためのライブラリです。
Angularなどと併用できますが、Reactと使用するのが最も相性がいいようです。
導入
今回のアプリではReactと使用しています。
以下のコマンドを実行することで、ReactとReduxを連携することができます。
npm install redux
npm install react-redux
スポンサードサーチ
state
アプリの状態を表します。
今回のアプリでは「入力された駅名」「選択されたジャンル」をstateとして管理します。
Action
Actionとは「何をする」という情報を持ったオブジェクトです。
例えば「駅名を入力した」「ジャンルを選択した」といった情報のことです。
またActionでは必ずtypeプロパティを持ちます。
このtypeプロパティがActionの種類を示します。
export const SEND_STATION = 'SEND_STATION';
export const SEND_GENRE = 'SEND_GENRE';
export const SEND_FEELING = 'SEND_FEELING';
export const SEND_SEAT = 'SEND_SEAT';
export const SEND_PAYMENT = 'SEND_PAYMENT';
export const sendStation = station => ({
type: SEND_STATION,
station,
})
export const sendGenre = genre => ({
type: SEND_GENRE,
genre,
})
export const sendSeat = seat => ({
type: SEND_SEAT,
seat,
})
export const sendPayment = payment => ({
type: SEND_PAYMENT,
payment,
})
スポンサードサーチ
Reducer
ReducerはActionとstateを元に、新しいstateを作成するメソッドです。
「駅名が入力されたら、駅名を更新する」というイメージです。
ReducerはActionのtypeに応じて、処理を書きます。
import {SEND_STATION} from '../action'
const initialAppState = {
station: '',
};
const stationreducer = (state = initialAppState, action) => {
// typeに応じて処理を書く
if (action.type === SEND_STATION) {
return Object.assign({}, state, {
station: action.station
});
} else {
return state;
}
};
export default stationreducer;
今回のアプリのように管理するstateが複数ある場合、stateごとに子Reducerを用意し、親Reducerでまとめて管理することができます。(RootReducerを作成できる)
その場合はcombineReducersを利用します。
import { combineReducers } from 'redux';
import station from './stationreducer';
import genre from './genrereducer';
import seat from './seatreducer';
import payment from './paymentreducer';
// RootReducers作成、ここに子Reducerを追加する
const reducer = combineReducers({
station,
genre,
seat,
payment
});
export default reducer;
Store
Storeはstateを保持している場所です。
アプリ内にStoreは1つだけです。
StoreはcreateStore()で作成します。
combineReducersで作成したRootReducerを渡すことで作成できます。
import React from 'react';
import ReactDOM from 'react-dom';
import './scss/index.scss';
import App from './components/App';
import reportWebVitals from './reportWebVitals';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducers/index';
// store作成
const store = createStore(reducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
スポンサードサーチ
mapStateToProps
mapStateToPropsはStoreのstateをpropsに詰め込むための関数です。
この関数によってstateの値をアプリ内で扱うことができるようになります。(画面に表示するなど)
mapDispatchToProps
mapDispatchToPropsはActionをDispatch(送信)するための関数です。
この関数によって、「入力された駅名で、stateを更新する」ことができるようになります。
この2つの関数の定義ができたら、connect()の引数に渡せばOKです。
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import Header from './header';
import { connect } from 'react-redux';
import * as actions from '../action';
class station extends Component {
constructor(props) {
super(props);
this.state = {
station: '恵比寿',
}
this.handleChange = this.handleChange.bind(this)
this.handleClick = this.handleClick.bind(this)
}
handleChange(e) {
this.setState({
station: e.target.value
})
}
handleClick() {
this.props.onClick(this.state.station);
this.props.history.push("/genre");
}
render() {
return (
<>
<Header />
<div className={'search'}>
<p className={'search-text'}>
地名などのキーワードを入力してください。<br />
半角スペース区切りで複数入力できます。
</p>
<input className={'search-textBox'} type='text' value={this.state.station} onChange={this.handleChange}></input>
<button className={'search-button'} onClick={this.handleClick}>次へ</button>
</div>
</>
);
}
}
// propsにstateの値を詰め込む(取得する)
const mapStateToProps = (state) => ({
station: state.station.station,
});
// actionをdispatchする(更新する)
function mapDispatchToProps(dispatch) {
return {
onClick(station) {
dispatch(actions.sendStation(station));
}
};
}
// connect()の引数に定義した関数を渡す
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(station));
Storeにアクセスする
Storeにアクセスするには、Providerというコンポーネントを使います。
作成したStoreをProviderに渡すことでStoreを利用できるようになります。
import React from 'react';
import ReactDOM from 'react-dom';
import './scss/index.scss';
import App from './components/App';
import reportWebVitals from './reportWebVitals';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducers/index';
// store作成
const store = createStore(reducer);
// Providerを使ってStoreにアクセスする
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
まとめ
以上がReactとReduxの基本的な使い方です。
Reduxを使うことでアプリの状態管理ができるようになります。
ぜひアプリ開発に取り入れてみてください。
参考
Redux入門【ダイジェスト版】10分で理解するReduxの基礎
webエンジニア転職を目指している方はこちら