[React] Hooks 알아보기 ( useState , useEffect )
함수 앞에 use 를 붙여 리액트에서 낚아서 슬 수 있도록 만든걸 react hooks 라고 부른다.
함수형 컴포넌트가 클래스형 컴포넌트같은 기능을 할 수 있게 해준다.
useState
class 컴포넌트로 state 를 활용해서 만들것이다.
import React from 'react';
export default class Example1 extends React.Component {
state = {count : 0};
render() {
const {count} = this.state; // state 는 객체
return (
<div>
<p>
You clicked {count} times
</p>
<button onClick={this.click}>Click me</button>
</div>
);
}
click = () => {
this.setState({count: this.state.count + 1});
}
}
이걸 function 컴포트로 변경하면
import React from "react";
export default function Example2() {
const [count , setCount] = React.useState(0);
// 앞선 state = {count :0} 을 뽑아내서 변경될 수 있는 값으로 사용하는 것
function click() {
setCount(count + 1);
}
return (
<div>
<p>You clicked {count} times</p>
<button onClick={click}>Click me</button>
</div>
);
}
→ function 컴포넌트에선 this 를 사용 x
둘 다 잘 나온다.
여기까지가 가장 기본적인 useState 를 활용하는 방법이다.
Example2 에서 useState 가 count 였다면 이번엔 객체로(useState : {count : 0} ) 받아볼 것이다.
import React from "react";
export default function Example3() {
const [state, setState] = React.useState({ count: 0 });
function click() {
setState({count : state.count + 1});
}
return (
<div>
<p>You clicked {state.count} times</p>
<button onClick={click}>Click me</button>
</div>
);
}
여기서 setState 안에 함수로 넣을 수도 있다.
function click() {
setState(state => ({
count : state.count + 1,
}));
}
useState 가 나오면서 Function Component가 더이상 Stateless Component 가 아니게 되었다.
왜 class 컴포넌트가 아닌 function 컴포넌트에서 상태성을 사용하려고 하느냐 ?
- 컴포넌트 사이에서 상태와 관련 로직을 재사용 하기 어렵다.
- 복잡한 컴포넌트들은 이해하기 어렵다.
- class 는 사람과 기계를 혼동시킨다. (컴파일 단계에서 코드를 최적화하기 어렵게 만든다.)
- this.state 는 로직에서 레퍼런스를 공유하기 때문에 문제가 발생할 수 있다.
useEffect
종류
- → componentDidUpdate
- →componentWillUnmount
- → componentDidMount
import React from "react";
export default class Example4 extends React.Component {
state = { count: 0 };
render() {
const { count } = this.state;
return (
<div>
<p>You clicked {count} times</p>
<button onClick={this.click}>Click me</button>
</div>
);
}
componentDidMount() {
//최초의 랜더가 실행된 직후
console.log('componentDidMount' , this.state.count);
}
componentDidUpdate() {
console.log("componentDidUpdate", this.state.count);
}
click = () => {
this.setState({ count: this.state.count + 1 });
};
}
Example1 을 복사해서 사용한다.
저렇게 각각 DidMount 와 DidUpdate 를 콘솔로 출력해보면
이렇게 최초에 DidMount 가 한번 출력되고 그 이후로 DidUpdate 가 클릭할때마다 출력된다.
import React from "react";
export default function Example5() {
const [count, setCount] = React.useState(0);
// 앞선 state = {count :0} 을 뽑아내서 변경될 수 있는 값으로 사용하는 것
React.useEffect(() => {
console.log('componentDidMount & componentDidUpdate', count);
}, []) // 두 상황 모두 실행되는 역할
function click() {
setCount(count + 1);
}
return (
<div>
<p>You clicked {count} times</p>
<button onClick={click}>Click me</button>
</div>
);
}
Example2 복사해서 사용
결국 componentDidMount 의 역할을 하는걸 볼 수 있다.
추가설명
React.useEffect(() => {
console.log("componentDidMount ");
return () => {
//cleanup
//이 위치가 componentWillUNmount 의 역할을 하고있다.
}
}, []); // 두 상황 모두 실행되는 역할 , 뒤에 배열은 실행되는 타이밍을 조절한다.
// 빈 배열을 두면 최초에만 실행된다.
React.useEffect(() => {
console.log("componentDidMount & componentDidUpdate by count", count);
return () => {
console.log('cleanup by count', count);
} // useEffect 가 실행되기 이전의값으로 return 부분을 실행한다.
//
}, [count]);
우리는 위에서 useEffect 가 DidMount 의 역할을 하는것을 알아냈다. useEffect 내부에 return 값을 넣으면 전문용어로 “cleanup” 이라고 한다.
먼저, 매번 업데이트 되는 값을 넣기 위해 [] 안에 count 를 넣었다.
그리고 return 안에 count 와 밖의 괄호 안의 count 를 비교해보면
이렇게 나온다. 즉, return 내부는 useEffect 가 실행되기 이전의 값으로 실행되는걸 알 수 있다.