네.. 오늘은 새로운 친구랑 함께하는 림졍입니둥.
일단 후기요? 너무 좋아요.
일단 백틱이 너무나도 잘되구요. 타건감은 말해뭐혀.
무엇보다 손꾸락에 느껴지는 피로도도 조금 많이 줄어든 느낌?
(이래서 다들 키보드에 돈을 많이 쓰는군요.. 이제서야 알았습니다)
여튼 오늘도 빠르게 강의내용 정리좀 해보겠습니다.
가시죠.
React (리액트) 강의 정리 - 숙련 ver. (이이이어서)
리덕스를 너무나도 우습게 보았다.. 큰났네 이거 🤦🏻♂️
Custom Hooks
컴포넌트에서 구현해온 useState & 핸들러, 추출해서 따로 빼놓은 것
- input 갯수만큼 늘어나는 useState, event handler
[src/App.jsx]
//input 구현 + useState로 각 input value 관리하는 코오드.
import React from "react";
import { useState } from "react";
const App = () => {
// input의 갯수가 늘어날때마다 state와 handler가 같이 증가한다.
const [title, setTitle] = useState("");
const onChangeTitleHandler = (e) => {
setTitle(e.target.value);
};
// input의 갯수가 늘어날때마다 state와 handler가 같이 증가한다.
const [body, setBody] = useState("");
const onChangeBodyHandler = (e) => {
setBody(e.target.value);
};
return (
<div>
<input
type="text"
name="title"
value={title}
onChange={onChangeTitleHandler}
/>
<input
type="text"
name="title"
value={body}
onChange={onChangeBodyHandler}
/>
</div>
);
};
export default App;
[정리]
변화되는 값에 따른 리렌더링을 위해 useState 여러번 사용
( input의 개수가 증가 시, useState와 이벤트핸들러도 같이 증가 → 코드 중복 발생 )
위의 코드에선 input이 단지 2개라 때문에 복잡해보이지 않지만.. 만약 input이 수십개가 되면? 중복코드 더 많아질 예정..
∴ 반복되는 로직 or 중복되는 코드, 우리만의 훅( = 커스텀 훅)을 통해서 관리 가능.
추가) Custom hook 생성 시, 고려해야하는 것
- 커스텀 훅의 함수 이름, use로 시작 (예: useInput).
- 파일 이름의 경우 use로 시작할 필요 X, 원하는 대로 지정 가능
+) 보관은 아래의 이미지를 참고하자..
- 코드 구현하기 (예시 참고)
[ src/hooks/useInput.js ]
import React, { useState } from "react";
const useInput = () => {
// 2. value는 useState로 관리하고,
const [value, setValue] = useState("");
// 3. 핸들러 로직도 구현합니다.
const handler = (e) => {
setValue(e.target.value);
};
// 1. 이 훅은 [ ] 을 반환하는데, 첫번째는 value, 두번째는 핸들러를 반환합니다.
return [value, handler];
};
export default useInput;
이제 실제로 시연해보자.
[ src/App.jsx ]
import React from "react";
import useInput from "./hooks/useInput";
const App = () => {
// 우리가 만든 훅을 마치 원래 있던 훅인것마냥 사용해봅니다.
const [title, onChangeTitleHandler] = useInput();
const [body, onChangeBodyHandler] = useInput();
return (
<div>
<input
type="text"
name="title"
value={title}
onChange={onChangeTitleHandler}
/>
<input
type="text"
name="title"
value={body}
onChange={onChangeBodyHandler}
/>
</div>
);
};
export default App;
커스텀훅을 만들기전과 동일한 작동 + 중복코드 제거 → 전체적인 코드량 감소
∴ 여러가지 기능을 구현하면서 중복되는 로직이 있다? → 훅으로 뺄 수 있을지 생각해보며 코딩해보기
Redux
중앙 state 관리소 를 사용할 수 있게 도와주는 패키지 (전역 상태관리 라이브러리)
애플리케이션의 상태 관리, 효율적으로 만들기 위해 사용
- Redux의 필요성
상태 관리가 복잡해질수록 컴포넌트 간의 데이터 전달이 어려워짐 코드 가독성 및 유지보수성 저하.
Redux 사용 시, 중앙에서 상태 관리 → 상태, 일관성 유지 + 예측 가능 상태 관리 가능해짐
Props로 State를 공유시, 발생하는 문제점 (이미지 참조)
- 컴포넌트 → 컴포넌트로 state 보내기 위해서는 반드시 부모관계 필요
- 조부모 컴포넌트 → 손자 컴포넌트로 값을 보내고자 할 때도 반드시 부모를 거쳐야..
(부모는 그게 필요없어도 불필요하게 거쳐가야하는 통로 역할을 해줘야함) - 자식 컴포넌트 → 부모 컴포넌트로 값 보내기 X
∴ Redux 를 사용하잔아여? 부모관계 없어도 되고 중간에 의미없는 컴포넌트 거칠 필요도 없다...
결론은 만-능이다. 기억하세요.
Global state / Local state
Local state (지역상태) : 개별 컴포넌트 내에서만 관리되는 상태. 특정 컴포넌트에서만 필요한 데이터 관리에 적합
Global state (전역상태) : 여러 컴포넌트에서 공통으로 필요로 하는 상태. 중앙 관리시, 데이터 동기화와 상태 관리가 용이
+) Context API가 있는데 Redux로 Global state를 구우우욷이 관리하면 좋은 이유?
- 성능 최적화
- 상태 변경 시 관련된 컴포넌트만 선택적 업데이트 가능, 성능 관리 용이.
- cf. Context API : 하위의 모든 컴포넌트를 리렌더링 (전역 상태 관리 가능, 복잡한 상태 관리 로직 구현엔 한계 존재. )
- 상태 로직의 중앙화와 일관성
- 애플리케이션 상태, 하나의 저장소(store)에 저장 + 상태 로직, 중앙에서 관리
→ 더 일관성 있고 예측 가능한 상태 변경 가능해짐. - 디버깅/테스팅 용이 (상태 변경 로직, 리듀서에 의해 처리되기 때문)
- 강력한 미들웨어와 개발 도구
- 다양한 미들웨어를 지원, 비동기 작업, 로깅, 상태 변경에 대한 추가 처리 등 복잡한 기능 구현가능.
- Redux DevTools → 상태 변화 모니터링, 롤백 등의 기능을 제공
- 유지보수 용이
- 액션, 리듀서, 스토어로 구분된 구조 → 코드의 가독성 및 유지보수성 향상
Redux 설정
- Redux 설치
2개의 패키지 설치 (아래의 코드, 터미널에 입력해서 설치하자!)
yarn add redux react-redux
# 아래와 같은 의미, react-redux = Redux, React에서 사용할 수 있도록 연결시켜주는 패키지
yarn add redux
yarn add react-redux
- 폴더 구조 생성하기
- src 폴더 안에 redux 폴더 생성
- redux 폴더 안에 config, modules 폴더 생성
- config 폴더 안에 configStore.js파일 생성
[폴더 및 파일 역할정리]
- redux : 리덕스 관련 코드 모두 모아 놓을 폴더
- config : 리덕스 설정 관련 파일들이 놓어질 폴더
- configStore : 중앙 state 관리소(Store) 만드는 설정 코드들이 있는 파일
- modules : 만들 State들의 그룹
ex) If to-do list 제작 시, to-do list에 필요한 state들을 모을 todos.js를 생성 (todos.js = 하나의 모듈)
- 설정코드 작성 시, 주의사항
- 이렇게 설정을 하라고 안내한거니 코드 분석 금지 ❌
- 사용 “방법”을 중점으로 공부하기. 결론 = 쓰는 방법만 익히자.
[src/configStore.js] 에 아래 코드 입력
import { createStore } from "redux";
import { combineReducers } from "redux";
/*
1. createStore()
리덕스의 가장 핵심이 되는 스토어를 만드는 메소드(함수) 입니다.
리덕스는 단일 스토어로 모든 상태 트리를 관리한다고 설명해 드렸죠?
리덕스를 사용할 시 creatorStore를 호출할 일은 한 번밖에 없을 거예요.
*/
/*
2. combineReducers()
리덕스는 action —> dispatch —> reducer 순으로 동작한다고 말씀드렸죠?
이때 애플리케이션이 복잡해지게 되면 reducer 부분을 여러 개로 나눠야 하는 경우가 발생합니다.
combineReducers은 여러 개의 독립적인 reducer의 반환 값을 하나의 상태 객체로 만들어줍니다.
*/
const rootReducer = combineReducers({});
const store = createStore(rootReducer);
export default store;
[index.js] 에 아래 내용 입력하기 (디렉토리 가장 최상단에 위치)
// 원래부터 있던 코드
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
// 우리가 추가할 코드
import store from "./redux/config/configStore";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
//App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
- 모듈(State의 그룹) 만들기
- modules 폴더에 counter.js 파일 생성
- 코드 뚱땅뚱땅 작성하기.
전체 코드 - [ src/redux/modules/counter.js ]
// 초기 상태값 : 어떤 State의 초기값을 정해주는 것. (useState에서 () 안에 초기값 지정하는 것과 같음)
const initialState = {
number: 0,
};
// 리듀서 : 변화를 일으키는 함수 (리듀서 = 함수다 정도만이라도 기억하기.)
const counter = (state = initialState, action) => {
switch (action.type) {
default:
return state;
}
};
// 모듈파일에서는 리듀서를 export default 한다.
export default counter;
- 카운터 모듈, Store에 연결
why? → 아직까진 모듈과 스토어가 각각 따로 분리되어 있는 상태, State Store에서 꺼낼 수 없음..
[configStore.js]로 이동하여 아래 코드 추가. (파일경로 : src/redux/config/configStore.js )
// 원래 있던 코드
import { createStore } from "redux";
import { combineReducers } from "redux";
// 새롭게 추가한 부분
import counter from "../modules/counter";
const rootReducer = combineReducers({
counter: counter, // <-- 새롭게 추가한 부분
});
const store = createStore(rootReducer);
export default store;
결론 : store와 모듈을 연결시키는 코드, 우리가 모듈을 추가할 때마다 똑같이 진행해주면 된다..
- Store & 모듈 연결 확인하기
useSelector 사용 → 컴포넌트에서 store 조회할 때 사용하는 훅 ((매우중요))
useSelector의 사용법
// 1. store에서 꺼낸 값을 할당 할 변수를 선언
const number =
// 2. useSelector()를 변수에 할당
const number = useSelector()
// 3. useSelector의 인자에 화살표 함수를 넣어주기
const number = useSelector( ()=>{} )
// 4. 화살표 함수의 인자에서 값을 꺼내 return
// +) state 확인해보기 위해 console.log 사용됨.
const number = useSelector((state) => {
console.log(state)
return state
});
활용 - [ src/App.js ]
// 기존 코드 모두 삭제 후 아래 코드를 입력해주기.
import React from "react";
import { useSelector } from "react-redux"; // import
const App = () => {
const counterStore = useSelector((state) => state); // 추가
console.log(counterStore); // 스토어를 조회를 위해 사용
return <div></div>;
}
export default App;
[in colsole] - console.log(counterStore); 조회
[결과 및 정리]
객체 내부에 그 안에 counter 라는 값 존재. ( counter 라는 모듈의 state 조회 가능 )
∴ 화살표 함수에서 꺼낸 state 인자 → 모든 리덕스 모듈의 최상위 객체인 Root State
If 컴포넌트에서 'number' 라는 값을 사용하고 싶다.. 아래 코드처럼 꺼내서 사용하자.
const number = useSelector(state => state.counter.number); // 0
마무리 - 새로운 영역에 도전하는 것만큼 짜릿한건 또 없지.
어쩌다보니 도망치는 이미지(?)가 되었지만
... 네 저 스낀다드 포기하고 챌린지로 갑니다.
라이브 코딩이 절대 싫어서는 아니고...요 (실은 이것도 맞긴 한데...조금?)
배우는 내용 <<<<< 라이브 코딩 비중인 것 같은 느낌이 드는 것도 있고
조금 더 성장해보고 싶은 욕구도 들어서요..? (는 무슨 지금도 따라가기 벅차하면서.ㄷㄷ)
여튼 그래서 오늘부터 한번 스터디.. 도 해보고
여러가지 우당탕 쿠당탕 시작해-보렵니다 하하
ENTJ - 도전정신 = 시체 는 공식이거든요.
뭐 막상 가서 잘할..수도 있잖아요?
암튼 뭐 오늘은 여기서 마무리짓고
내일도 리덕스 강의정리 들고올게요... 굳빠12
KPT 회고
- Keep : 탈 스낀다드 림졍! 대단하다! 아니 엄청나!
- Problem : ... 그래서 개인과제는 언제해?
- Try : 이번주는 주말까지 TIL 쓰기.. 주르륵..
(\ /)
( -.-)
o_(")(") The End.
'React TIL' 카테고리의 다른 글
쉬어가는 TIME - 개인과제 중간점검(?) (feat. 꿀팁) (1) | 2024.11.09 |
---|---|
[React] Day_36 데일리 정리 (4) | 2024.11.08 |
[React] Day_34 데일리 정리 (1) | 2024.11.06 |
[React] Day_33 데일리 정리 (2) | 2024.11.05 |
[React] Day_32 데일리 정리 (5) | 2024.11.04 |