함수 컴포넌트
장점
단점
→ 이문제를 해결해 주기 위해 React v16.8 업뎃이후 태어난 Hook .
Hook 의 태어난 Story
래퍼 지옥이란? ( 콜백 지옥이랑 비슷한 모습)
👉 처음 리액 리액트를 접했을 때
UI을 재사용 가능한 component들로 나누고 다른데서도 쓸 수 있도록 작성했지만,
로직이 UI 및 리액트 life cycle에 너무 밀접하게 결합되어 있었기 때문에 어려움을 겪음.
중복된 코드들이 늘어나기 시작함.
( 문제의 중복 되어 있는 코드)
👉 방법을 찾음!
화면에서 재사용 가능한 로직만을 분리해서 컴포넌트 (component) 로 만들고,
재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법.
💥 하지만 이 방법을 쓰니 코드의 모습들에서 문제가 보이기 시작함.
계속 다른 부분에 있는 파라미터(parameter) 로 받아와서 코드를 쓰고 감싸주다 보니..
‼‼위 코드의 모습을 보면 여러 로직이 componentWillUnmount, componentDidMount 등의 리액트 life cycle에 흩어지게 되고, 함수는 단일 책임 원칙을 벗어나게 되고, 코드는 복잡해지고, 테스트는 점차 어려워지게 된다.
🚩로직을 분리하면서도 wrapper hells을 피할 수 있고, 리액트 component life cycle에도 종속적이지 않게 코딩을 어떻게 할까?
바뀌기 전
ex)
{/* Hook 함수가 도입되기 전의 모습*/}
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "이름"
};
}
render() {
return <input value={name} onClick={(e) => this.setState({ name : e.target.value })} />;
}
}
👉바뀐 후
이제는 단순히 기존 class의 render() 단계에 해당되는 로직에 집중하면 된다.
그리고 state가 필요한 경우 useState를 사용하여 hook 을 한다.
ex)
import { useState } from 'react';
function Example() {
const [name, setName] = useState("이름");
return <input value={name} onChange={(e) => setName(e.target.value)} />;
}
👉 useState는 인자로 초기값을 받고, 현재 상태(name)와 현재 상태를 업데이트할 수 있는 함수(setName)를 반환해준다. 훨씬 코드가 깔끔해짐.
[ 2가지의 side effects ]
- 정리를 이용하지 않은 함수
- 정리를 이용하는 함수
1. 정리(Clean-up)를 이용하지 않는 Effects
ex) 정리가 필요하지 않은것은 그 어떤것도 반환하지 않는다.
useEffect(() => {
document.title = `You clicked ${count} times`;
});
2. 정리(Clean-up)를 이용하는 Effects
ex)
const [enteredEmail, setEnteredEmail] = useState(''); //이메일(아이디) 입력값 저장
const [emailIsValid, setEmailIsValid] = useState(); //패스워드 입력값 저장
const [formIsValid, setFormIsValid] = useState(false); //유효성 여부 저장
useEffect(()=>{
const identifier = setTimeout(() => {
console.log("Checking from validity!")
setFormIsValid(
enteredEmail.includes('@') && enteredPassword.trim().length > 6
)
}, 500) //5초가 지난 후에 수행
return ()=>{
console.log("CLEAN UP!")
clearTimeout(identifier)
} //클린업 함수
}, [enteredEmail, enteredPassword])
const emailChangeHandler = (event) => {
setEnteredEmail(event.target.value);
};
const passwordChangeHandler = (event) => {
setEnteredPassword(event.target.value);
};
클린업 함수가 사용된 부분
()=>{
console.log("CLEAN UP!")
clearTimeout(identifier)
} //클린업 함수
[ 📍비동기는 논블록을 기반한 방식인거고 📌논블럭은 다른 브라우저가 실행될때,
대기할 필요 없이 다른 데이터들도 처리할수 있음 ]
📌 논블록이란?
논블록이란 비동기 개념에서 만들어진 상태로
브라우저가(크롬) 실행되는 시간이 10분(요청)이라고 가정했을시에
브라우저가(크롬) 이 오픈(결과) 되기전까지 다른 브라우저(사파리 등등)은 시간을
대기 하지 않고 제약없이 자유롭게 사용할수 있는 상황을 논블록 상태.
페이지 이동, 특정 버튼 누르면 컴포넌트가 사라짐
특정 페이지를 나가버리거나 안나오게 해버리거나
비동기는 진행중인데 이벤트가 사라져 버리니까
에러가 나와, 이럴때 쓰는게 클린업 ( 이런 문제를 해결하기 위한 기술 개념)
🤔 useContext의 'Context'란?
React로 개발을 하다보면, 상위 컴포넌트로부터 하위 컴포넌트에게 데이터를 전달해야하거나,
컴포넌트 트리 내에서 데이터를 전역족으로 관리를 할 상황이 자주 일어난다고 한다.
이때 컴포넌트 트리 구조가 복잡하거나 거대한 경우에는, 단순히 데이터를 넘겨주기 위한 용도의 컴포넌트가 생성되기도 한다.
ex) X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.
A→B→C→D
X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.
장기적으로 봤을 때 컴포넌트 트리 구조가 굉장히 복잡해지기 때문에 컴포넌트를 관리하는 것이 어려워지게 된다.
💥이때 !! context를 이용하면, 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에서 데이터를 사용할 수 있다.
Context를 이용하면 각 컴포넌트에게 데이터를 명시적으로 props로 넘겨주지 않아도 컴포넌트끼리 데이터를 공유할 수 있다.
Context는 Provider와 Consumer로 이뤄지는데, MVC 패턴이나 Observer 패턴과 비슷하게 Provider의 값이 변경되면 Consumer가 이를 감지하고 자동으로 하위 컴포넌트에 변경 사항을 반영해준다.
출처: https://velog.io/@gwak2837/React-Hooks%EC%9D%98-%EC%9D%B4%ED%95%B4
1.createContext : context 객체를 생성한다.
2.provider : 생성한 context를 하위 컴포넌트에게 전달하는 역할을 한다.
3.consumer : context의 변화를 감시하는 컴포넌트이다
컴포넌트 트리 전체에서 언제 어디서나 전역적(global)
으로 데이터를 사용할 수 있게 해주는 것이 Context
이다.