일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프로그래머스 프론트엔드 데브코스
- 이벤트 수식어
- 쌓임맥락
- vuex map
- 리스트 렌더링
- react next
- 프로그래머스 데브코스 프론트엔드
- git 같은계정 다른 컴퓨터
- 고양이 사진 검색기
- SCSS extend
- Spacer
- nextjs사용법
- vue 이벤트 수신
- 프로그래머스 데브코스
- 리액트
- SCSS forward
- intersection opserver
- KDT 프로그래머스 데브코스 프론트엔드
- SCSS import
- 폼 입력 바인딩
- SCSS use
- vue 지역 컴포넌트
- 다른컴퓨터에서 git사용
- KDT 프로그래머스
- 프로그래머스 K_Digital Training
- postcss
- flex
- netlify redirect
- vue mixin
- Vue
- Today
- Total
혼자 적어보는 노트
프로그래머스 데브코스 TIL - Day 56 본문
✅ 오늘의 학습
📌 React (8)
- API를 활용한 프로젝트
- axios를 이용한 네트워크 API 실습
- react-router
여러 컴포넌트 한줄에 불러오기
작은 단위의 컴포넌트들이 들어있는 base폴더에서
컴포넌트를 가져오게되면 아래와 같이 컴포넌트마다 한 줄씩 불러와야한다.
import Header from './components/base/Header';
import Spinner from './components/base/Spinner';
가져오는 컴포넌트가 많아질 수록 길게 작성이 되는데
components폴더의 index파일을 사용하여 간결하게 작성하게 만들 수 있다.
[components/index.js]
export { default as Header } from './base/Header';
export { default as Spinner } from './base/Spinner';
[App.js]
import { Header, Spinner } from './components';
index.js폴더 안에 각각의 컴포넌트를 불러와서 export를 해주면
다른 컴포넌트에서 불러올 때 중괄호로 묶어서 불러올 수 있다!
ContextAPI + useReducer
이전강의에서는 context API내부에서 useState를 통해서 값을 관리하고
내부에서 값을 변경하는 함수를 생성하여 내보내주었는데
useReducer를 사용하면 업데이트 하는 항목을 내부적인 로직으로 만들어 둘 수 있다.
[contexts/postsProvider.js]
import {
createContext,
useCallback,
useContext,
useEffect,
useReducer,
} from 'react';
const PostContext = createContext();
export const usePostContext = () => useContext(PostContext);
// useContext hook에 담아서 전달
const reducer = (state, action) => {
// 받는 action에 따라 상태를 어떻게 변경하여 처리할 지 작성
switch (action.type) {
case 'INIT_POSTS': {
return action.payload;
}
case 'ADD_POST': {
return [...state, action.payload];
}
case 'DELETE_POST': {
const payload = action.payload;
return state.filter((item) => item.id !== payload.id);
}
default: {
console.error('Wrong type');
break;
}
}
};
const PostProvider = ({ children, initialPosts, handleDeletePost }) => {
const [posts, dispatch] = useReducer(reducer, initialPosts || []);
// useReducer(reducer, 초기 상태)
useEffect(() => {
dispatch({ type: 'INIT_POSTS', payload: initialPosts || [] });
// 사용자가 마음대로 설정해서 사용해도 됨.
}, [initialPosts]);
const onDeletePost = useCallback(
// 해당 함수가 호출되면 dispatch를 통해 reducer에 정의된 로직이 실행된다.
async (id) => {
const payload = await handleDeletePost(id);
dispatch({ type: 'DELETE_POST', payload });
},
[handleDeletePost],
);
return (
<PostContext.Provider value={{ posts, onDeletePost }}>{children}</PostContext.Provider>
);
// 상위 컴포넌트에서 전달받은 데이터를 자식 컴포넌트에게 뿌려준다.
};
[App.js]
function App() {
const initialPosts = useAsync(async () => {
return await axios
.get('https://jsonplaceholder.typicode.com/posts')
.then((res) => res.data);
}, []);
const handleDeletePost = useCallback(async (id) => {
return await axios
.delete(`https://jsonplaceholder.typicode.com/posts/${id}`)
.then(() => ({ id }));
}, []);
return (
<PostsProvider
initialPosts={initialPosts.value}
handleDeletePost={handleDeletePost}
>
<div className="App">
{initialPosts.isLoading ? <Spinner /> : <PostList />}
</div>
</PostsProvider>
);
}
export default App;
데이터 흐름
1. 최상위 컴포넌트인 App에서 비동기 요청을 보내고 받은 결과 값 또는 비동기 함수를 provider를 통해 전달.
2. provider안에서 props로 받은 값 혹은 함수를 사용하여 dispatch를 하는 "새로운 함수"를 만들어서
자식요소에게 전달하기 위해 내부의 provider로 전달.
* 여기서 state는 무조건 dispatch와 action을 통해 수정된다.
3. useContext를 통해 context 내부에서 관리되고있는 state 및 state를 변경하는 함수를 꺼내서
컴포넌트에서 사용.
데이터가 전달되고 사용되는 과정은 위처럼 세 파트로 나눌 수 있었지만
provider로 두번 넘겨주는 과정 때문에 처음엔 조금 헷갈렸다.
redux와 비슷하지만 Redux처럼 스토어 하나로 처리하지 않고 provider로 감싸서 처리를 해줘야 한다는 불편함이 있었다.
React-router
이전에 v6을 조금 쓰다가 불편해서 v5를 사용했었는데
v6에도 익숙해지기위해 이번 강의는 v6으로 마이그레이션하여 작성해보았다.
import { Route, Routes } from 'react-router-dom';
import DefaultTemplate from '@components/template/DefaultTemplate';
import { PostsPage, PostPage, NotFoundPage } from '@pages';
function App() {
return (
<DefaultTemplate>
<Routes>
<Route path="/" element={<h1>Home</h1>} />
<Route path="/posts" element={<PostsPage />} />
<Route path="/posts/:postId" element={<PostPage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</DefaultTemplate>
);
}
export default App;
route를 작성하는 부분에 있어서 v5 -> v6 차이점은
switch가 Routes로 변경이 되고 exact를 작성하지 않아도 된다는 점과
props를 통해 컴포넌트를 전달한다는 점이다.
DefaultTemplate
이전에는 상단 메뉴와같이 고정적으로 들어가는 것은 그냥 App컴포넌트 상단에 작성을 하였는데
DefaultTemplate를 사용하여 App내부의 Routes를 감싸서 따로 관리할 수 있다는 점을 알게 되었다.
const DefaultTemplate = ({ children }) => {
return (
<div>
<Menu />
<main>{children}</main>
</div>
);
};
✍ 느낀 점
React 기본 강의는 이번 강의가 마지막이고 이제 배운 것을 활용해서 프로젝트를 만들어야한다.
이전에 children을 사용해서 무언가를 만드는 것이 조금 미흡했었는데
강의에서 사례를 많이 보여주셔서 앞으로 전보다는 활용을 많이 할 수 있을 듯 했다.
이전에 혼자서 공부를 했었을 때는 검색이나 여러 시행착오를 겪으면서 작성을 했었고
심지어 진땀빼며 작성한 코드들도 효율성 측면에서 좋지 않다고 느꼈었는데
이번 리액트 강의를 듣고나니 약간 지름길을 알게 된 것 같은 느낌이었다. 그만큼 많은 도움이 되었다!!
'스터디' 카테고리의 다른 글
프로그래머스 데브코스 TIL - Day 70 (0) | 2022.06.25 |
---|---|
프로그래머스 데브코스 TIL - Day 69 (0) | 2022.06.23 |
프로그래머스 데브코스 TIL - Day 55 (0) | 2022.06.03 |
프로그래머스 데브코스 TIL - Day 54 (0) | 2022.06.02 |
프로그래머스 데브코스 TIL - Day 53 (0) | 2022.06.02 |