newsapi.org에 있는 데이터를 가져오기 위해서는, newsapi.org에서 제공하는 API를 이용해야 한다. 이때, 비동기 통신(newsapi.org 서버와의 통신)을 Redux-Saga를 이용해 데이터를 가져와보자.
순서
- ‘create-react-app’으로 프로젝트 생성
- 프로젝트 앱의 index.js에서 Redux와 연동
- store.js에서 Redux의 store를 세팅
- Redux와 연결할 Container 컴포넌트와 화면에 보여줄 각 컴포넌트 생성
- 통신할 API와 관련된 코드 작성
- action 및 action types 등록
- Container 컴포넌트에서 액션을 dispatch
- 액션을 받아 비동기 통신 처리를 할 saga 작성
- saga 이후, state를 변경할 reducer 작성
1. 프로젝트 앱의 index.js에서 Redux와 연동
index.js
‘create-react-app’ 한 이후, 처음 상태1
2
3
4
5
6
7
8
9
10
11
12
13
14// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
1-1. Redux 설치1
npm install --save react-redux
1-2. Redux-saga 설치1
npm install --save redux-saga
1-3. Redux 세팅 및 Redux-saga 적용
1 | // index.js |
2. store.js에서 Redux의 store를 세팅
1 | // store.js |
이렇게 하여, Redux store 세팅이 완료되었다.
3. Redux와 연결할 Container 컴포넌트와 화면에 보여줄 각 컴포넌트 생성
- Contianer 컴포넌트 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// ContainerRedux.js
import React, { Component } from 'react';
import { connect } from "react-redux";
import Button from './components/Button'
import Loading from './components/Loading'
import News from './components/News'
class ContainerRedux extends Component {
render() {
return (
<div className="">
<Button
/>
<Loading
/>
<News
/>
</div>
);
}
}
function mapStateToProps(state) {
return {
};
}
function mapDispatchToProps(dispatch) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ContainerRedux);
- 각 컴포넌트 생성
Button.js1
2
3
4
5
6
7
8
9
10
11
12
13// Button.js
import React from 'react';
const Button = ({onClickGetNews}) => {
return (
<div>
<button onClick={onClickGetNews}>get news</button>
</div>
)
}
export default Button;
Loading.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// Loading.js
import React from 'react';
const Loading = ({ loading }) => {
return (
<div>
{
loading ?
<div>
<h1>LOADING ...</h1>
</div>
:
null
}
</div>
)
}
export default Loading;
News.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// News.js
import React from 'react';
const News = ({ articles }) => {
return (
<div>
{
articles ?
<div>
{
articles.map((article, key) => {
return <div key={key}>
<span>{article.title}</span>
<img src={article.urlToImage} alt=""/>
</div>
})
}
</div>
:
null
}
</div>
)
}
export default News;
4. 통신할 API와 관련된 코드 작성
4-1. axios 설치1
npm install axios
4-2. api 코드 작성1
2
3
4
5
6
7// index.js in 'api' folder
import axios from 'axios';
export function getNews() {
return axios.get('https://newsapi.org/v1/articles?source=cnn&apiKey=APIKEY')
}
APIKEY는 News API에서 API KEY를 요청하여 받아야 한다.
5. action 및 action types 등록
5-1. action creator 생성1
2
3
4
5
6
7// action.js
import * as types from './actionType';
export const getNews = () => ({
type: types.GET_NEWS_REQUEST,
});
5-2. action type 생성1
2
3
4
5// actionType.js
export const GET_NEWS_REQUEST = "GET_NEWS_REQUEST";
export const GET_NEWS_SUCCESS = "GET_NEWS_SUCCESS";
export const GET_NEWS_FAILURE = "GET_NEWS_FAILURE";
6. Container 컴포넌트에서 액션을 dispatch(state 및 dispatch 코드 작성)
1 | // ContainerRedux.js |
7. 액션을 받아 비동기 통신 처리를 할 saga 작성
1 | // index.js in 'sagas' folder |
effect란, 각각의 task를 기술하기 위한 명령어이다. 대표적인 effect는 다음과 같다.
- take: Action을 기다린다.
- put: Action을 Dispatch 한다.
- call: Promise의 완료를 기다린다.(서버 API와의 통신할 때 주로 사용)
- fork: 다른 task를 시작한다.
- join: 다른 task의 종료를 기다린다.
- select: state로부터 필요한 데이터를 꺼낸다.
8. saga 이후, state를 변경할 reducer 작성
1 | // reducer.js |
화면 재로딩(refresh) 없이, post 요청한 데이터 같은 화면에 바로 가져오는 방법
만약, 화면에서 데이터를 서버에 보내고(post), 보낸 데이터와 관련된 데이터를 받아와야 하는 경우를 saga에서 처리할 수 있다.
예를 들어, ‘기부하기’ 버튼을 클릭해서, donation 액션을 dispatch 할때, payload로 기부자 이름과 메세지를 보낸다고 하자. 그리고, 아래 화면에는 기부자와 메세지를 보여준다고 해보자. 그럼 refresh 없이, ‘기부하기’ 버튼 클릭 후, 바로 화면에 데이터를 보여줄려면 어떻게 해야할까?
이것을 saga에서 처리하는 데,
- 데이터를 서버에 보낸다.(yield call(API, payload))
- 성공하면(res.status === 200), 서버에서 데이터를 받아오는 API를 get 요청하여 받아온다.(yield call(getAPI))
- 성공하면(res.status === 200), 액션을 dispatch 하여, reducer에서 새로 받아온 데이터로 값을 변경하여, 화면에 데이터를 뿌려주게 된다.
1 | function* addDonation() { |