Skip to content

Commit 5dfa603

Browse files
committed
4th release
1 parent 89c61bd commit 5dfa603

29 files changed

+4342
-31
lines changed

SUMMARY.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,29 @@
5151
- [2. 파라미터와 쿼리](./react-router/02-params-and-query.md)
5252
- [3. 서브라우트](./react-router/03-subroutes.md)
5353
- [4. 리액트 라우터 부가기능](./react-router/04-extra.md)
54-
- [5. useReactRouter Hook 사용하기](./react-router/05-use-router-hook.md)
54+
- [5. useReactRouter Hook 사용하기](./react-router/05-use-router-hook.md)
55+
- [6장. 리덕스](./redux/README.md)
56+
- [1. 리덕스에서 사용되는 키워드 숙지하기](./redux/01-keywords.md)
57+
- [2. 리덕스의 3가지 규칙](./redux/02-rules.md)
58+
- [3. 리덕스 사용 할 준비하기](./redux/03-prepare.md)
59+
- [4. 리덕스 모듈 만들기](./redux/04-make-modules.md)
60+
- [5. 카운터 구현하기](./redux/05-counter.md)
61+
- [6. 리덕스 개발자도구 적용하기](./redux/06-redux-devtools.md)
62+
- [7. 할 일 목록 구현하기](./redux/07-implement-todos.md)
63+
- [8. useSelector 최적화](./redux/08-optimize-useSelector.md)
64+
- [9. connect 함수](./redux/09-connect.md)
65+
- [정리](./redux/CONCLUSION.md)
66+
- [7장. 리덕스 미들웨어](./redux-middleware/README.md)
67+
- [1. 리덕스 프로젝트 준비하기](./redux-middleware/01-prepare.md)
68+
- [2. 미들웨어 만들어보고 이해하기](./redux-middleware/02-make-middleware.md)
69+
- [3. redux-logger 사용 및 미들웨어와 DevTools 함께 사용하기](./redux-middleware/03-logger-and-devtools.md)
70+
- [4. redux-thunk](./redux-middleware/04-redux-thunk.md)
71+
- [5. redux-thunk로 프로미스 다루기](./redux-middleware/05-redux-thunk-with-promise.md)
72+
- [6. API 재로딩 문제 해결하기](./redux-middleware/06-fix-reloading.md)
73+
- [7. thunk에서 라우터 연동하기](./redux-middleware/07-router-with-thunk.md)
74+
- [8. json-server](./redux-middleware/08-json-server.md)
75+
- [9. CORS 와 Webpack DevServer Proxy](./redux-middleware/09-cors-and-proxy.md)
76+
- [10. redux-saga](./redux-middleware/10-redux-saga.md)
77+
- [11. redux-saga 로 프로미스 다루기](./redux-middleware/11-redux-saga-with-promise.md)
78+
- [12. saga에서 라우터 연동하기](./redux-middleware/12-redux-saga-with-router.md)
79+
- [정리](./redux-middleware/CONCLUSION.md)

integrate-api/01-basic.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ function Users() {
136136
// loading 상태를 true 로 바꿉니다.
137137
setLoading(true);
138138
const response = await axios.get(
139-
'https://jsonplaceholder.typicode.com/users/showmeerror'
139+
'https://jsonplaceholder.typicode.com/users'
140140
);
141141
setUsers(response.data); // 데이터는 response.data 안에 들어있습니다.
142142
} catch (e) {

react-router/02-params-and-query.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ import React from 'react';
133133
import qs from 'qs';
134134

135135
const About = ({ location }) => {
136-
const query = qs.parse(location.search.substr(1)); // substr 은 맨 앞의 "?" 문자열을 없애줍니다.
136+
const query = qs.parse(location.search, {
137+
ignoreQueryPrefix: true
138+
});
137139
const detail = query.detail === 'true'; // 쿼리의 파싱결과값은 문자열입니다.
138140

139141
return (

react-router/04-extra.md

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,31 @@
1010

1111
#### src/HistorySample.js
1212
```javascript
13-
import React, { Component } from 'react';
13+
import React, { useEffect } from 'react';
1414

15-
class HistorySample extends Component {
16-
// 뒤로가기
17-
handleGoBack = () => {
18-
this.props.history.goBack();
15+
function HistorySample({ history }) {
16+
const goBack = () => {
17+
history.goBack();
1918
};
2019

21-
// 홈으로 이동
22-
handleGoHome = () => {
23-
this.props.history.push('/home');
20+
const goHome = () => {
21+
history.push('/');
2422
};
2523

26-
componentDidMount() {
27-
// 이걸 설정하고 나면 페이지에 변화가 생기려고 할 때 마다 정말 나갈거냐고 질문
28-
this.unblock = this.props.history.block('정말 떠나실건가요?');
29-
}
30-
31-
componentWillUnmount() {
32-
// 컴포넌트가 언마운트 되면, 그만 물음
33-
if (this.unblock) {
34-
this.unblock();
35-
}
36-
}
37-
38-
render() {
39-
return (
40-
<div>
41-
<button onClick={this.handleGoBack}>뒤로</button>
42-
<button onClick={this.handleGoHome}>홈으로</button>
43-
</div>
44-
);
45-
}
24+
useEffect(() => {
25+
console.log(history);
26+
const unblock = history.block('정말 떠나실건가요?');
27+
return () => {
28+
unblock();
29+
};
30+
}, [history]);
31+
32+
return (
33+
<div>
34+
<button onClick={goBack}>뒤로가기</button>
35+
<button onClick={goHome}>홈으로</button>
36+
</div>
37+
);
4638
}
4739

4840
export default HistorySample;

redux-middleware/01-prepare.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
## 1. 리덕스 프로젝트 준비하기
2+
3+
리덕스 미들웨어를 공부해보기 전에, 리덕스 프로젝트를 먼저 새로 생성해주도록 하겠습니다.
4+
5+
다음 명령어를 사용하여 새로운 프로젝트를 준비해주세요.
6+
7+
```bash
8+
$ npx create-react-app learn-redux-middleware
9+
```
10+
11+
> 이 섹션의 코드는 [여기](https://codesandbox.io/s/vzui1)서 확인 가능합니다.
12+
13+
그리고 해당 디렉터리에서 redux와 react-redux를 설치해주세요.
14+
15+
```bash
16+
$ cd learn-redux-middleware
17+
$ yarn add redux react-redux
18+
```
19+
20+
이제, 카운터 예제를 만들어보도록 하겠습니다.
21+
22+
### 리덕스 모듈 준비
23+
24+
우리는 액션 타입, 액션 생성함수, 리듀서를 한 파일에 작성하는 Ducks 패턴을 사용하도록 하겠습니다. src 디렉터리에 modules 디렉터리를 만들고, 그 안에 counter.js 라는 파일을 생성해서 다음과 같이 작성해주세요.
25+
26+
원래 Ducks 패턴을 따르는 리덕스 모듈에서는 액션 이름에 `'counter/INCREASE'` 이런식으로 앞부분에 접두어를 두지만, 이번에는 액션이름이 중복되는 일이 없으니, 편의상 생략하도록 하겠습니다.
27+
28+
#### modules/counter.js
29+
```javascript
30+
// 액션 타입
31+
const INCREASE = 'INCREASE';
32+
const DECREASE = 'DECREASE';
33+
34+
// 액션 생성 함수
35+
export const increase = () => ({ type: INCREASE });
36+
export const decrease = () => ({ type: DECREASE });
37+
38+
// 초깃값 (상태가 객체가 아니라 그냥 숫자여도 상관 없습니다.)
39+
const initialState = 0;
40+
41+
export default function counter(state = initialState, action) {
42+
switch (action.type) {
43+
case INCREASE:
44+
return state + 1;
45+
case DECREASE:
46+
return state - 1;
47+
default:
48+
return state;
49+
}
50+
}
51+
```
52+
53+
그 다음에는 루트 리듀서를 만들어주세요. 물론 지금은 서브리듀서가 하나밖에 없는 상황이지만, 나중에 몇개 더 만들 것입니다.
54+
55+
#### modules/index.js
56+
```javascript
57+
import { combineReducers } from 'redux';
58+
import counter from './counter';
59+
60+
const rootReducer = combineReducers({ counter });
61+
62+
export default rootReducer;
63+
```
64+
65+
66+
### 프로젝트에 리덕스 적용
67+
68+
프로젝트에 리덕스를 적용해주세요. 프로젝트에 리덕스를 적용 할 때에는 src 디렉터리의 index.js 에서 루트리듀서를 불러와서 이를 통해 새로운 스토어를 만들고 Provider 를 사용해서 프로젝트에 적용을 합니다.
69+
70+
#### index.js
71+
```javascript
72+
import React from 'react';
73+
import ReactDOM from 'react-dom';
74+
import './index.css';
75+
import App from './App';
76+
import * as serviceWorker from './serviceWorker';
77+
import { createStore } from 'redux';
78+
import { Provider } from 'react-redux';
79+
import rootReducer from './modules';
80+
81+
const store = createStore(rootReducer);
82+
83+
ReactDOM.render(
84+
<Provider store={store}>
85+
<App />
86+
</Provider>,
87+
document.getElementById('root')
88+
);
89+
90+
// If you want your app to work offline and load faster, you can change
91+
// unregister() to register() below. Note this comes with some pitfalls.
92+
// Learn more about service workers: https://bit.ly/CRA-PWA
93+
serviceWorker.unregister();
94+
```
95+
96+
97+
### 프리젠테이셔널 컴포넌트 준비
98+
99+
그 다음, 프리젠테이셔널 컴포넌트 Counter 를 준비해주겠습니다. components 디렉터리에 Counter.js 파일을 만드세요. 해당 컴포넌트에서는 number, onIncrease, onDecrease를 props로 받아옵니다.
100+
101+
#### components/Counter.js
102+
```javascript
103+
import React from 'react';
104+
105+
function Counter({ number, onIncrease, onDecrease }) {
106+
return (
107+
<div>
108+
<h1>{number}</h1>
109+
<button onClick={onIncrease}>+1</button>
110+
<button onClick={onDecrease}>-1</button>
111+
</div>
112+
);
113+
}
114+
115+
export default Counter;
116+
```
117+
118+
### 컨테이너 만들기
119+
120+
그리고 컨테이너도 만들어줍시다.
121+
122+
#### containers/CounterContainer.js
123+
```javascript
124+
import React from 'react';
125+
import Counter from '../components/Counter';
126+
import { useSelector, useDispatch } from 'react-redux';
127+
import { increase, decrease } from '../modules/counter';
128+
129+
function CounterContainer() {
130+
const number = useSelector(state => state.counter);
131+
const dispatch = useDispatch();
132+
133+
const onIncrease = () => {
134+
dispatch(increase());
135+
};
136+
const onDecrease = () => {
137+
dispatch(decrease());
138+
};
139+
140+
return (
141+
<Counter number={number} onIncrease={onIncrease} onDecrease={onDecrease} />
142+
);
143+
}
144+
145+
export default CounterContainer;
146+
```
147+
148+
이제 App 에서 CounterContainer를 렌더링을 하고, `yarn start` 를 해서 개발 서버를 구동해보세요.
149+
150+
#### App.js
151+
```javascript
152+
import React from 'react';
153+
import CounterContainer from './containers/CounterContainer';
154+
155+
function App() {
156+
return <CounterContainer />;
157+
}
158+
159+
export default App;
160+
```
161+
162+
163+
이제 카운터가 작동하는지 확인해보세요.
164+
165+
![](https://i.imgur.com/MTeKPV9.png)
166+
167+
이제 리덕스 미들웨어를 직접 만들어볼 준비가 끝났습니다.

0 commit comments

Comments
 (0)