[React] Front-End

[FE] Redux (2) : react-redux / reducer 분리 / Middleware / import vs require

ddgoori 2021. 7. 16. 17:13

리덕스 폴더구조

 

// 길어질만한건 action과 reducer 두 가지

 

reducers 라는 폴더

*보통 대표적인 애들이 index.js

reducer.js

- 모듈로 만들어주면 됨

- reducer.js 하단에 아래 코드

module.exports = reducer;

 

actions 라는 폴더

action.js

- 함수들은 acrion creator

 

index.js에서 reducer, action 불러옴

const reducer = require('./reducer');
const { logIn, logOut, addPost } = require('./action');

 

액션도

 

사용자액션 

게시글에대한 액션

 

이렇게 나뉠 수 있음. 

 

 

 

 

 

 

분리의 기준? 데이터!

 

- 관련된건 최대한 묶어주기

-  보통 배열이 되고 덩치가 커질만한 것은 밖으로 빼주는 것이 좋음

 

예제)

 

// redux/index.js

const { createStore } = require('redux');
const reducer = require('./reducer');
const { logIn, logOut, addPost } = require('./action');

const initialStat = {

	user:{
    	isLoggIn: true,
        data: null,
    },
    posts: [],
    comments: [],
    favorites: [],
    history: [],
    likes: [],
    followers: [],
};

 

이런 객체들이 늘어나면?

메모리...? 웬만해서는 문제 안되는 수준 => 얕은 복사라서!

참조가 유지되어서 메모리 2배로 잡아먹거나 그러진 않음..

 

화면에 보일정도만 데이터를 가져오는 것이 좋음

블로그: 다음 게시물 보는데 오래 걸리고

페이스북: 다음 게시물 빨리 봐야하고,,

 

서비스 특성에 따라 다름

 

 

 

 

리듀서 쪼개기: CombineReducer(리덕스에서 제공함)

 

폴더구조

 

리듀서는 함수라서 combineReducer라고 리덕스에서 제공하는 함수를 통해 쪼갬

아래 처럼 리듀서 쪼갤 수 있음!

 

reducers

- rootReducer.js => combineReducers

- loginReducer.js

- postReducer.js

- searchReducer.js

.

.

import { combineReducers } from 'redux';

import loginReducer from './loginReducer';
import postReducer from './postReducer';
import searchReducer from './searchReducer';

const rootReducer = history =>
  combineReducers({
    loginReducer,
    postReducer,
    searchReducer,
  });

export default rootReducer;

 

 

 

 

 

분리를 하면 문제가 생김 -> 그걸 보여주기위해 비동기와 미들웨어에 대해 알아보쟈

 

리덕스 미들웨어

 

액션은 그냥 객체라서 기본적으로 동기임

그 사이에 비동기가 들어갈 틈이 없음.

 

그래서 리덕스에서 미들웨어 사용

dispatch를 하면 그 action이 reducer와 매칭됨

=> action이 reducer와 매칭될 때 아래의 코드에 걸림.

=> 이 매칭되는 사이에 작동하는게 middleware! (디스패치와 리듀서 그 사이에 동작하기  때문에 미들웨어라고 이름 붙임)

=> 미들웨어 유명한게 redux-saga

// redux/reducers/user.js

const postReducer = (prevState = initialState, action) => {
	switch (action.type) {
    	case 'ADD_POST':
        	return [...prevStae, action.data];
        default: 
        	return prevState;
    
    }
};

module.exports = postReducer;

 

 

compose는 합성하는 함수

applyMidlware(),

devtool, 등 합성할 떄 씀

 

// redux/index.js

const { createStore, compose, applyMiddleware } = require('redux');
const reducer = require('./reducers');
const { addPost } = require('./actions/post');
const { logIn, logOut } = require('./actions/user');

const initialState = {
	user: {
    	isLoggingIn: true,
        data: null,
    }
    posts: [],
};

// 3단 고차 함수가 들어감
// 함수들이 중첩됨.
// (디스패치와 리듀서 그 사이에 동작하기  때문에 미들웨어라고 이름 붙임)
const firstMiddleware = (store) => (dispatch) => (action) => {
	console.log('액션로깅',action); // <- 부가적인 동작하나가 추가됨!! (기본기능 실행되기 전)
    // 기능추가
    dispatch(action); // 이건 기본기능임 
    // 기능추가 (기본기능 실행된 후)
    // console.log('액션 끝!');

};

const enhancer = compose(
	applyMiddleware(firstMiddleware),
);

const store = createStore(reducer, initialState, enhancer);
store.subscribe(listner() => {  //react-redux안에 있음
	console.log('changed!'); //화면 바꿔주는 코드 여기서

});

 

subscribe?

 

subscribe(listener)

변경사항에 대한 리스너를 추가합니다. 리스너는 액션이 보내져서 상태 트리의 일부가 변경될 수 있을 때마다 호출됩니다. 콜백 안에서 현재 상태 트리를 읽으려면 getState()를 호출하면 됩니다.

 

 

Store

 

lunit.gitbook.io

 

 

 

redux-thunk

- 미들웨어 라이브러리 종류임. Thunks VS Sagas 로 비교 많이 됨

- Redux 미들웨어는 dispatch() 메소드를 통해 store로 가고 있는 액션을 가로채는 코드다.

 

기본적으로 액션은 동기,

비동기라는 것을 보여주기 위해 객체 대신 액션을 함수로 넣어준다.

 


const firstMiddleware = (store) => (dispatch) => (action) => {
	console.log('액션로깅',action); // <- 부가적인 동작하나가 추가됨!! (기본기능 실행되기 전)
    // 기능추가
    dispatch(action); // 이건 기본기능임 
    // 기능추가 (기본기능 실행된 후)
    // console.log('액션 끝!');

};

const thunkMiddleware = (store) => (dispatch) => (action) => {
	if(typeof action === 'function') { // 비동기
    	retrun action(store.dispatch, store.getState);
    }
    return dispatch(action);
};

const enhancer = compose(
	applyMiddleware(firstMiddleware),
);

 

 

동기는 action에서 객체를 리턴

비동기는 비동기라는 것을 보여주기 위해서 함수를 리턴

 

// actions/user.js

const Login = () => { // async action creator 함수리턴
	return (dispatch, getState) => {
    	dispatch(logInRequest());  // 동기 부르기
        setTimeout( handler: () => { // 로그인 네트워크 통신 임의 구현
        	dispatch(logInSuccess()); // 동기 부르기
        }, timeout: 2000);
    };
};

// 동기 액션들간의 실행 속도롤 조작하는 정도로 비동기 구현 가능

const logInRequest = (data) => {
	return {
    	type: 'LOG_IN_REQUEST',
        data,
    }
};

const logInSuccess = (data) => {
	return {
    	type:
    }
}

const logIn = (data) => { // sync action creator 객체리턴
	return {	// action
		type: 'LOG_IN',
		data,
	};
};

 

 

 

import vs require

 

생각해보니 차이점으로 import는 정적 임포트, require는 동적 임포트라는 차이가 더 있네요. import는 항상 파일 상단에, require는 파일 아무데서나 쓸 수 있습니다.

 

require => 노드의 모듈시스템

파일에서 module.exports = NumberBaseball; 했을 시

require로 사용가능

 

 

노드의 모듈 문법 => 노드에서는 얘만 지원함(common js 가 정통적임)

const React = require('react');
module.exports = NumberBaseball;

 

 

ES2015 문법임  => 바벨이 import를 require로 바꿔줌(클라이언트)

import React from 'react';
export default NumberBaseball;

 

리액트에서 가져오는 것 합쳐줄 수 있음

import React, { Component } from 'react';


{ } 는 구조분해 => 변수나 값같은걸 따로 export 했을 때 

- default는 한번만 쓸 수 있고

- export const hello = 'hello';의 경우엔 변수명만 안겹치면 여러개 쓸 수 있음

import React, { Component } from 'react';
// React는 export default로 되어있겠군
// Component는 export const ~로 되어있겠군

class NumberBaseball extends Component {

}

export const hello = 'hello'; // import { hello, bye }
export const bye = 'bye'; //
export default NumberBaseball; // import NumberBaseball

 

그래서 webpack 에서는 아래처럼 선언해줘야함.. 노드 모듈!!!써야함

const path = require('path');

 

 

 

 

*출처: 아래 강이 내용 복습

 

Redux vs MobX (둘 다 배우자!) - 인프런 | 강의

리덕스와 몹엑스 뭘 선택할지 고민되시나요? 일단 둘 다 배우고나서 고민합시다!, [사진] 리덕스 vs 몹엑스 뭘 선택할지 고민된다면 일단 둘 다 배우자! 🗒 강의소개 React 프로그래밍을 할 때, 상

www.inflearn.com