Rental Application (React & Spring boot Microservice) - 25 : redux-saga
10880 ワード
#1 Redux-sagaアプリケーション
redux-sagaは、これらの動作を監視し、特定の動作が発生した場合に処理する.まずredux-sagaとaxiosをインストールします.axiosは、APIをバインドするためのライブラリです.
npm install redux-saga axios
import axios from 'axios';
const client = axios.create();
export default client;
CORSエラーを回避するために、エージェントを8900番ポート(apigate-service)に設定します.{
...
"proxy": "http://localhost:8900/"
}
管理メンバーに必要なapiは、次のように作成されます.既存のauth-serviceのエンドポイントurlを使用します.import client from './client';
export const login = ({
email,
password
}) => client.post('/auth-service/login', {
email,
password
});
export const register = ({
email,
password,
nickname,
phoneNumber
}) => client.post('/auth-service/register', {
email,
password,
nickname,
phoneNumber
});
export const getUser = ({ userId }) => client.getUser('/auth-service/:userId/getUser', { userId });
次に、動作関数の開始時間と終了時間を示すload reducsモジュールを作成します.import { createAction, handleActions } from "redux-actions";
const START_LOADING = 'loading/START_LOADING';
const FINISH_LOADING = 'loading/FINISH_LOADING';
export const startLoading = createAction(
START_LOADING,
requestType => requestType,
);
export const finishLoading = createAction(
FINISH_LOADING,
requestType => requestType,
);
const initialState = {};
const loading = handleActions(
{
[START_LOADING]: (state, action) => ({
...state,
[action.payload]: true,
}),
[FINISH_LOADING]: (state, action) => ({
...state,
[action.payload]: false,
}),
},
initialState,
);
export default loading;
import { combineReducers } from "redux";
import auth from './auth';
import loading from './loading';
const rootReducer = combineReducers(
{
loading,
auth,
},
);
export default rootReducer;
createRequestSagaは、動作関数が正常に動作しているときにAPI内のデータの要求と応答を処理するユーティリティ関数です.import { call, put } from "@redux-saga/effects";
import { startLoading, finishLoading } from "../modules/loading";
export const createRequestActionTypes = type => {
const SUCCESS = `${type}_SUCCESS`;
const FAILURE = `${type}_FAILURE`;
return [type, SUCCESS, FAILURE];
};
export default function createRequestSaga(type, request) {
const SUCCESS = `${type}_SUCCESS`;
const FAILURE = `${type}_FAILURE`;
return function*(action) {
yield(put(startLoading(type)));
try {
const response = yield call(request, action.payload);
yield put({
type: SUCCESS,
payload: response.data,
});
} catch(e) {
yield put({
type: FAILURE,
payload: e,
error: true,
});
}
yield put(finishLoading(type));
};
}
1)createRequestActionType:アクションタイプのコード.たとえば、ログインしたアクションタイプを「auth/LOgin」、「auth/LOgin SUCCESS」、「auth/LOgin FAILURE」と呼ぶ場合、この方法を使用してアクションタイプに変数を付与します.2)createRequestSaga:Sagaリクエストコード.たとえば、auth/LOginという名前のタイプ、アイデンティティ、パスワードです./src/lib/api/auth.jsに存在するloginリクエストを受信すると、ジェネレータ関数を使用してリクエストが処理されます.
では、これらのコードを利用してapi処理のコードを完成します.
import { createAction, handleActions } from "redux-actions";
import produce from 'immer';
import { takeLatest } from "@redux-saga/core/effects";
import createRequestSaga,{
createRequestActionTypes
} from "../lib/createRequestSaga";
import * as authAPI from '../lib/api/auth';
const CHANGE_FIELD = 'auth/CHANGE_FIELD';
const INITIALIZE_FORM = 'auth/INITIALIZE_FORM';
const [LOGIN, LOGIN_SUCCESS, LOGIN_FAILURE] = createRequestActionTypes('auth/LOGIN');
const [REGISTER, REGISTER_SUCCESS, REGISTER_FAILURE] = createRequestActionTypes('auth/REGISTER');
export const changeField = createAction(
CHANGE_FIELD, ({
form,
key,
value
}) => ({
form,
key,
value,
}),
);
export const initializeForm = createAction(INITIALIZE_FORM, form => form);
export const login = createAction(LOGIN, ({
email,
password
}) => ({
email,
password
}));
export const register = createAction(REGISTER, ({
email,
password,
nickname,
phoneNumber
}) => ({
email,
password,
nickname,
phoneNumber
}));
const loginSaga = createRequestSaga(LOGIN, authAPI.login);
const registerSaga = createRequestSaga(REGISTER, authAPI.register);
export function* authSaga() {
yield takeLatest(LOGIN, loginSaga);
yield takeLatest(REGISTER, registerSaga);
}
const initialState = {
register: {
email: '',
password: '',
passwordConfirm: '',
nickname: '',
phoneNumber: '',
},
login: {
email: '',
password: '',
},
auth: null,
authError: null,
};
const auth = handleActions(
{
[CHANGE_FIELD]: (state, { payload: { form, key, value }}) =>
produce(state, draft => {
draft[form][key] = value;
}),
[INITIALIZE_FORM]: (state, { payload: form }) => ({
...state,
[form]: initialState[form],
authError: null,
}),
[LOGIN_SUCCESS]: (state, { payload: auth }) => ({
...state,
authError: null,
auth
}),
[LOGIN_FAILURE]: (state, { payload: error }) => ({
...state,
authError: error,
}),
[REGISTER_SUCCESS]: (state, { payload: auth }) => ({
...state,
authError: null,
auth,
}),
[REGISTER_FAILURE]: (state, { payload: error }) => ({
...state,
authError: error,
}),
},
initialState,
);
export default auth;
import { combineReducers } from "redux";
import { all } from 'redux-saga/effects';
import auth, { authSaga } from './auth';
import loading from './loading';
const rootReducer = combineReducers(
{
loading,
auth,
},
);
export function* rootSaga() {
yield all([authSaga()]);
}
export default rootReducer;
./src/index.jsimport React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import createSagaMiddleware from '@redux-saga/core';
import rootReducer, { rootSaga } from './modules';
import { BrowserRouter } from 'react-router-dom';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(sagaMiddleware))
);
sagaMiddleware.run(rootSaga);
ReactDOM.render(
<Provider store={ store }>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
reportWebVitals();
道徳に関連するコードを作成したので、Formコンポーネントの登録とログインを継続できるようにコードを作成します.2会員加入
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { changeField, initializeForm, register } from '../../modules/auth';
import AuthForm from './AuthForm';
import { withRouter } from 'react-router-dom';
const RegisterForm = ({ history }) => {
const dispatch = useDispatch();
const {
form,
auth,
authError
} = useSelector(({
auth,
}) => ({
form: auth.register,
auth: auth.auth,
authError: auth.authError,
}));
...
// Handler that registers form
const onSubmit = e => {
e.preventDefault();
const {
email,
password,
passwordConfirm,
nickname,
phoneNumber,
} = form;
if(password !== passwordConfirm) {
// setError
return;
}
if([
email,
password,
passwordConfirm,
nickname,
phoneNumber,
].includes('')) {
// setError
return;
}
dispatch(register({
email,
password,
nickname,
phoneNumber,
}));
history.push('/');
};
...
};
export default withRouter(RegisterForm);
discovery-service、apiGateway-service、config-server、auth-serviceを起動し、テスト結果を表示します.会員が加入している姿がよく見えます.
次の記事では、ログインに関連するredoxを作成する方法について説明します.
リファレンス
Reference
この問題について(Rental Application (React & Spring boot Microservice) - 25 : redux-saga), 我々は、より多くの情報をここで見つけました https://velog.io/@biuea/Rental-Application-React-Spring-boot-Microservice-25-redux-sagaテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol