MVC패턴
모델Model : 모델은 앱이 포함해야할 데이터가 무엇인지를 정의. ( ==데이터베이스 )
뷰View: 레이아웃과 화면을 처리합니다.(==화면 jsx, vue)
컨트롤러Controller: 명령을 모델과 뷰 부분으로 라우팅합니다. (==비동기통신하는 부분, composable)
mvc패턴으로 짜주려면 누구 하나가 모든것을 다 처리하면 안된다.
각각의 역할 만큼만 할 수 있도록 만들어주어야한다.
따라서 view에서 비동기통신과 관련된 것들을 모~두 하지 않는것이 좋고, 따로 services 폴더를 만들어 관리한다.
수정 전 코드 app.jsx
import './App.css';
import React, {useState, useEffect} from 'react';
import VideoList from './components/video_list/index.jsx';
import Search from './components/search/index.jsx';
function App({ youtube }) {
const [ videos, setVideos ] = useState([]);
const apikey = '123456789testkey';
const requestOptions = {
method: 'GET',
redirect: 'follow'
};
useEffect(() => {
console.log('effect')
fetch(
`https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&type=video&key=${apikey}`
, requestOptions
)
.then(response => response.json())
.then(result => setVideos(result.items))
.catch(error => console.log('error', error));
}, [])
const handleSearch = (data) => {
const url = 'https://www.googleapis.com/youtube/v3/search'
fetch(
`${url}?part=snippet&q=${data}&maxResults=25&type=video&key=${apikey}`
, requestOptions
)
.then(response => response.json())
.then(result => result.items.map(item => ({...item, id: item.id.videoId })))
.then(items => setVideos(items))
.catch(error => console.log('error', error));
}
return (
<React.Fragment>
<Search handleSearch={handleSearch}></Search>
<VideoList videos={videos}></VideoList>
</React.Fragment>
);
}
export default App;
언뜻봐도 알겠지만 모든 통신을 app.jsx 파일에서, 즉 view에서 모든 것을 컨트롤하고 있는 상태이다.
MVC 패턴으로 수정하기
1. src밑에 services 폴더 만들고 하위에 index.ts 파일 만들기
//services/index.ts
class Youtube {
constructor(key) {
this.key = key;
this.requestOptions = {
method: 'GET',
redirect: 'follow'
};
}
async mostPopular() {
console.log('key', this.key)
try {
const response = await fetch(
`https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&type=video&key=${this.key}`,
this.requestOptions
);
const result_1 = await response.json();
return result_1.items;
} catch (error) {
return console.log('error', error);
}
}
async search(query) {
const url = 'https://www.googleapis.com/youtube/v3/search'
try {
const response = await fetch(
`${url}?part=snippet&q=${query}&maxResults=25&type=video&key=${this.key}`,
this.requestOptions
);
const result_1 = await response.json();
return result_1.items;
} catch (error) {
return console.log('error', error);
}
}
}
export default Youtube;
2. src/index.js 에서 인스턴스 새로 만들어서 선언해두기 (각 페이지에서 하는것은 좋지 않음)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import Youtube from './services/youtube';
const youtube = new Youtube(process.env.REACT_APP_YOTUBE_API_KEY);
ReactDOM.render(
<React.StrictMode>
<App youtube={youtube} />
</React.StrictMode>,
document.getElementById('root')
);
youtube 를 선언해서 그 안에 services에서 받아온 Youtube class를 새로 만들어서 App 컴포넌트로 넘겨준다.
여기서 new Youtube() 안의 apikey부분은 env 파일을 만들어서 따로 관리한다. (관련 내용은 아래 url 참고)
[React] 깃허브에 올리면 안되는 apikey 설정하는법
이슈 api key는 소스작업시에 올라가면 안되는 아이므로 꽁꽁 숨겨두어야하는데 어떻게 숨겨두는지 강의를 통해 알았다. 해결 1. 루트폴더에 .env파일을 만든다. 2. .env 파일안에 대문자로 이루어진
joannashin.tistory.com
3. src/app.jsx 에서 (필요한 페이지에서 ) 넘긴 youtube 가져다가 사용하기
import './App.css';
import React, {useState, useEffect} from 'react';
import VideoList from './components/video_list/index.jsx';
import Search from './components/search/index.jsx';
function App({ youtube }) {
const [ videos, setVideos ] = useState([]);
const handleSearch = (query) => {
youtube
.search(query)
.then(items => setVideos(items));
}
useEffect(() => {
youtube
.mostPopular()
.then(items => setVideos(items));
}, []);
return (
<React.Fragment>
<Search handleSearch={handleSearch}></Search>
<VideoList videos={videos}></VideoList>
</React.Fragment>
);
}
export default App;
반응형
'React' 카테고리의 다른 글
[React & 환경세팅] .env 환경변수 파일 값 변경하기 (0) | 2022.03.16 |
---|---|
[React] useEffect란 ? ? ? (0) | 2022.02.24 |
[React] 깃허브에 올리면 안되는 apikey 설정하는법 (.env 파일) (0) | 2022.02.21 |
[React 세팅] 리액트 create-react-app 세팅 오류 ! (You are running `create-react-app` 4.0.1, which is behind the latest release (5.0.0).) (0) | 2022.02.09 |
[React 기본] React Hook (0) | 2022.02.07 |