리덕스 폴더구조
// 길어질만한건 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?
변경사항에 대한 리스너를 추가합니다. 리스너는 액션이 보내져서 상태 트리의 일부가 변경될 수 있을 때마다 호출됩니다. 콜백 안에서 현재 상태 트리를 읽으려면 getState()를 호출하면 됩니다.
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');
*출처: 아래 강이 내용 복습
'[React] Front-End' 카테고리의 다른 글
[FE] Redux (4): Redux-Saga 의 필요성 / 사용법 (조현영 Redux vs Mobx 복습) (0) | 2021.07.18 |
---|---|
[FE] Redux (3): Redux-devtools / immer (조현영 Redux vs Mobx 복습) (1) | 2021.07.18 |
[FE] React 자동완성 : clg / rafce (0) | 2021.07.15 |
[FE] Redux (1) 개념 / 사용법 (제로초 Redux 강의 복습) (0) | 2021.07.14 |
[FE] JS ES6 : 화살표 함수 / Promise / async / await / Promiss.all() / Promise.race() (0) | 2021.07.06 |