Redux-sagaの使い方



Redux-Sagaとは?


既存のReduxスケジューリングは同期して実行できません.バックエンドからstoreにデータをロードすると、同期ロードに問題が発生する可能性があります.したがって、非同期ロードの方法が必要であるため、redux-sagaが必要であり、redux-sagaはreduxのミドルウェアがdispatchを非同期で実行するのを助けることができる.また,以前reduxでは補うことができなかったdispatchを1回実行せざるを得なかったタスクを2回実行すると,2回とも実行して問題になる場合があり,これを補うためにsagaは様々な内部手法を用いた.ユーザが誤って同じapiを複数回要求した場合、最近または最後のreqのresのみを受信することもできる.

先行知識(Generator)


正式に使用方法を理解する前に、sagaが使用するjavascript構文제너레이터を理解してから理解することができます.제네레이터を熟知することをお勧めします.

1.インストールと追加


設定
npm install redux-saga
storeフォルダでstoreのプリファレンスを個別に構成します.jsに記入します.
// store/configureStore.js

import { createWrapper } from "next-redux-wrapper";
import { applyMiddleware, compose, createStore } from "redux";
import {composeWithDevTools} from 'redux-devtools-extension';
import createSagaMiddleware from 'redux-saga';// 1.createSagaMiddleware 를 redux-saga에서 추가를 합니다.
import reducer from '../reducers';
import rootSaga from '../sagas'; // 2.sagas폴더를 만들어 rootSaga.js를 만들어 saga에 대한 내용을 안에다가 넣습니다.

const configureStore = () =>{
    const sagaMiddleware = createSagaMiddleware();//3. createSagaMiddleware 활성화.

    const middlewares = [sagaMiddleware]; //4.middlewares배열에 추가.

    const enhancer = process.env.NODE_ENV === 'production' ?
    compose(applyMiddleware(...middlewares)): 
    composeWithDevTools(applyMiddleware(...middlewares)); //기본 redux tool 활성화 설정
  
    const store = createStore(reducer,enhancer);

    store.sagaTask = sagaMiddleware.run(rootSaga);//5.rootSaga와 sagaMiddleware 바인딩해준다.

    return store;
};

const wrapper = createWrapper(configureStore,{
    debug:process.env.NODE_ENV === 'development',
});

export default wrapper;

2.rootSagaを作成します。


ReducsRootReducerのように、誰もがsagaファイルをコンパイルする役割を果たしています.
import {all,fork} from 'redux-saga/effects';
import userSaga from './user'; //유저정보를 담은 userSaga
import postSaga from './post'; //포스트정보 담은 postSaga


export default function* rootSaga() {//1
    yield all([ //all: 배열을 받고 받은 이펙트들을 등록해주는 역할
        fork(userSaga),
        fork(postSaga),
    ]);
}
allは配列を受け入れ、受信した効果を登録する.fork関数の実行に使用します.

3.それぞれ伝奇を作る。


ここでは、ログイン動作の例のみを作成します.
記述時には、コメント内のデジタルストリームを使用して記述すると理解しやすくなります.
import { all,fork,takeLatest,put,delay} from "@redux-saga/core/effects";
import { LOG_IN_SUCCESS,LOG_IN_FAILURE,LOG_IN_REQUEST} from "../reducers/user";
import axios from "axios";

function logInAPI(data){//4
    return axios.post('/api/login',data)
}

function* logIn(action){//3
    try{
    const result = yield call(logInAPI,action.data);//call: 비동기에서 await 같은 개념이다.

    //yield delay(1000);  백엔드 구축 안했을때 비동기 느낌 나기 위해서 1초딜레이 하고 실행.
    yield put({
        type:LOG_IN_SUCCESS,
        data:action.data
    })

    }catch(err){
        yield put({ // redux 액션으로 보내줌. put:dispatch라고 생각하면 편하다.
            type:LOG_IN_FAILURE,
            data:err.response.data,
        })
    }
}
}

function* watchLogIn(){//2.
    yield takeLatest(LOG_IN_REQUEST,logIn); //take 한번만 실행되고 이벤트 삭제된다.
    // 이벤트 리스너 느낌을 준다.
}

export default function* userSaga(){//1
    yield all([
        fork(watchLogIn),
    ])
}
call非同期概念では、実行が完了した後にのみ次のコードが実行される待機概念である.
誤ってtakeLatestを2回押した場合、前のイベントを無視して最後のイベントを実行します(通常、このオーバーヘッドは大きいです).
完成したら運転->両方ともフライパンの場合は後ろのは消します.
注意!2番reqをfront->back->に送信しますが、back->front路resは1番を送信します(つまり、サーバ側が2回保存されているかどうかを確認する必要があります).
すなわち、リフレッシュは2つを反映する
閉まるのを防ぐためにアクセルが付いていますput Reduxではdispatchに似ていると考えられる.take回のみ実行し、イベントを削除takeEveryを1回実行しても、イベントはリフレッシュされます.

4.減速機でユーザを実現する。

export const initialized ={
    logInLoading:false,//로그인 시도중
    logInDone: false,
    logInError:null,
    me:null,
    signUpData:{},
    loginData:{}
}

export const LOG_IN_REQUEST = 'LOG_IN_REQUEST';
export const LOG_IN_SUCCESS = 'LOG_IN_SUCCESS';
export const LOG_IN_FAILURE = 'LOG_IN_FAILURE';


export const loginRequestAction =(data)=>{

    return  {
        type:LOG_IN_REQUEST,
        data
    }
}


const dummyUser = (data) =>({
    ...data,
    nickname:'sungmin',
    id:1,
    Posts:[],
    Followings:[],
    Followers:[],
})

const reducer = (state=initialized,action)=>{
    switch(action.type){
        case LOG_IN_REQUEST:
            return {
                ...state,
                logInLoading:true,
                logOutError:null,
                logInDone:false
            }
        case LOG_IN_SUCCESS:
            return {
                    ...state,
                    logInLoading:false,
                    logInDone:true,
                    me:dummyUser(action.data),
            }
        case LOG_IN_FAILURE:
            return {
                ...state,
                logInDone:false,
                logInLoading:false,
                logInError:action.data
            }
        default:
            return state;
    }

}


export default reducer;