리액트를 처음 접했을 때 컴포넌트가 뭐지?라는 생각을 했다.
컴포넌트가 정확히 무엇인지 모른채로 프로젝트를 진행했고, 컴포넌트를 어깨 너머로 감만 잡고 넘어갔던 것 같다.
리액트를 너무 잘하고 싶어서, 기반을 단단하게 다지려고 처음부터 하려고 한다.
리액트! 기다려 너. 내가 잡아 버린다!
어렵지만 재밌어 리액트 혼내줄거야!
Component
리액트는 화면에서 Ul 요소를 구분할 때 '컴포넌트'라는 단위를 사용한다.
리액트에서 앱을 이루는 작은 조각이라고 볼 수 있다!
<입력(props)을 받아 출력(Element)하는 역할>
Component의 구성요소
1. Property(props)
부모 컴포넌트에서 자식 컴포넌트에 전달되는 데이터.
property값은 자식 컴포넌트에서 수정 불가
2.state
컴포넌트의 상태를 저장하고 수정 가능한 데이터
3. context
부모 컴포넌트에서 생성하여 모든 자식 컴포넌트에게 전달하는 데이터
컴포넌트의 개념 그 다음으로 이해해야 할 요소는! 바로 생명주기!!
이게 정~말 머리에 그려지지 않아서 애를 먹었다.
(리액트는 함수형과 클래스형으로 나뉜다)
리액트의 컴포넌트는 생명주기를 가진다.
생명주기란 컴포넌트가 생성되고 사용되고 소멸될 때 까지 일련의 과정을 말한다.
생명주기 안에서는 특정 시점에 자동으로 호출되는 메서드가 있는데, 이를 라이프 사이클 이벤트라고 한다.
출처: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
보기에 약간 어려운 느낌은 있지만 일목요연한 표다.
class component의 생명주기는 마운트/업데이트/언마운트로 나눌 수 있다.
1. 마운트
컴포넌트가 처음 실행이 될 때 생성단계를 마운트(Mount)라고 표현
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
constructor
constructor(props) {
super(props);
this.state = {};
}
컴포넌트 생성자 메서드로, 컴포넌트가 생성이 되면 제일 먼저 실행이 되는 메서드
state와 props를 접근하여 값을 할당 할 수 있습니다.
getDerivedStateFromProps
static getDerivedStateFromProps(props, state){
console.log('2. getDerivedStateFromProps call: ' +props.props_value);
return{};
}
getDerivedStateFromProps는 props로 받아온 것을
state에 설정하고 싶을 때 사용이 되며,
최초 마운트 시와 갱신 시, 모두에서 render 메서드를 호출하기 직전에 호출
특정 객체를 반환하게 되면 해당 객체의 값이 state로 갱신이 되며,
null을 반환하게 되면 아무 것도 갱신하지 않을 수 있다.
render
render()
render()은 컴포넌트를 렌더링 해주는 메서드
클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드
componentDidMount
componentDidMount()
컴포넌트가 마운트, 첫번째 렌더링이 된 직후 호출되는 메서드
이 시점에는 화면이 구현이 되어있는 상태
componentDidMount에서는 DOM에 접근하여 사용 가능
여기에서는 주로 AJAX 요청을 하거나,DOM에 속성을 읽거나 변경을 하는 작업
(setTimeout, setInterval 등등)
2. 업데이트
업데이트 단계는 컴포넌트의 Props나 state변경으로 인해 재렌더링이 발생할 때 일어나는
생명주기의 중요한 부분으로 컴포넌트의 업데이트 시에는 아래 메서드들 호출
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
getDerivedStateFromProps
getDerivedStateFromProps는 값이 갱신되어 업데이트 시에도 render 전에 메서드가 실행
shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState)
shouldComponentUpdate()는 컴포넌트를 다시 리렌더링 할지 말지 결정하는 메서드입니다.
props 또는 state가 새로운 값으로 갱신되어서 렌더링이 발생하기 직전에 호출
기본값은 true이며, return false를 하면 render을 취소할 수 있다.
그래서 주로 성능최적화를 위해 사용
render 렌더링
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate()는 가장 마지막으로 렌더링된 결과가 DOM 등에 반영되기 전에 호출
이 메서드를 사용을 하면 DOM 상태가 변경이 되기전의 값을 반환하여
componentDidUpdate에서 인자로 받아서 사용 가능
componentDidUpdate
componentDidUpdate(prevProps, prevState) {}
componentDidUpdate(prevProps) {
// 전형적인 사용 사례 (props 비교를 잊지 마세요)
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
componentDidUpdate()는 갱신이 일어난 직후에 호출
이 메서드는 최초 렌더링에서는 호출되지 않는다.
3.언마운트
언마운트(Unmount)라는것은, 컴포넌트가 화면에서 제거 되는것을 의미하며,
관련된 생명주기 메서드는 componentWillUnmount 하나다.
componentWillUnmount
componentWillUnmount()
컴포넌트가 사라지기 직전에 호출을 하고,
주로 여기서는 DOM에 등록했었던 이벤트들을 제거해주는 용도로 사용
Functional Componet 생명주기
리액트에서 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동 할 수 있게 해주는 함수
Hook은 class없이 React를 사용할 수 있게 한다.
🚩Hook 사용 규칙 두가지
- 최상위 에서만 Hook을 호출해야 한다
- 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.
- 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
- 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다.
- 일반 JS함수에서는 Hook을 호출해서는 안된다.
💡Hook의 종류와 정리
☑️ useState
상태 관리 [state이름, set이름] 순으로 반환 받아서 사용
const [state, setState] = useState(initialState);
☑️ useEffect
화면에 렌더링이 완료된 후에 수행되며componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것
❗️만약 화면을 다 그리기 이전에 동기화 되어야 하는 경우에는,useLayoutEffect를 활용하여 컴포넌트 렌더링 - useLayoutEffect 실행 - 화면 업데이트 순으로 effect를 실행
useEffect(() => {}); // 렌더링 결과가 실제 돔에 반영된 후마다 호출
useEffect(() => {}, []); // 컴포넌트가 처음 나타날때 한 번 호출
useEffect(() => {}, [의존성1, 의존성2, ..]); // 조건부 effect 발생, 의존성 중 하나가 변경된다면 effect는 항상 재생성됩니다.
useEffect안에서의 return은 정리 함수(clean-up)를 사용하기 위해 사용.
- 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행
- 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect 정리
☑️ useContext
Context API를 통해 만들어진 Context에서 제공하는 Value를 가져올 수 있다.
const value = useContext(MyContext);
컴포넌트에서 가장 가까운 <MyContext.Provider>가 갱신되면 이 Hook은 그 MyContext provider에게 전달된 가장 최신의 context value를 사용하여 렌더링을 트리거
☑️ useReducer
useState의 대체 함수로 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리 가능
컴포넌트 바깥에 로직을 작성할 수 도 있고, 심지어 다른 파일에 작성한 후 불러와서 사용 가능
reducer란 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수
const [state, dispatch] = useReducer(reducer, initialArg, init);
☑️ useRef
특정 DOM 선택할때 주로 쓰이며 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환
반환된 객체는 컴포넌트의 전 생애주기를 통해 유지
const refContainer = useRef(null);
☑️ useMemo
메모이제이션된 값을 반환
이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 함.
의존성이 변경되었을 때에 메모이제이션된 값만 다시 계산
의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
☑️ useCallback
메모이제이션 된 콜백을 반환
useMemo와 유사하게 이용되며 '함수'에 적용
의존성이 변경되었을때만 변경하기 때문에 특정 함수를 새로 만들지 않고 재사용가능
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
🐌결론 및 느낀점
오늘 초보자를 위한 리액트 200제를 1부터 풀기 시작했다.
사실 따라 적고 주석을 달면서 이해하려고 계속 쳐다보는 중이지만
아직도 언어가 낯설고 어려운 느낌이었다.
그 이유는 내가 기초부터 쌓지 않아서 라고 생각이 들었고, 처음부터 하나하나 다시 쌓아가려고 한다.
요즘엔 개발자 관련 서적을 매일 매일 등학교 하며 읽고 있다.
읽으면서 느낀 것은 정말 해결할 수 없는 문제는 없다. 문제를 해결하기 위해서는
꾸준히 개발 언어를 공부하는 것과 기본기를 탄탄하게 해서 오류가 생겼을 때 해결해 나가는 방법을 찾아야 한다.
오늘 복기하는 시간을 가지면서 머릿 속이 깔끔하게 정리된 기분이 든다!
이것만으로도 나는 행보케~ 만족은 못하지만 움하하하
참고사이트
'developer Studying > React' 카테고리의 다른 글
[react] Props 낱낱이 파헤치기 (1) | 2024.09.10 |
---|---|
[react]Map()함수 (3) | 2024.09.06 |