그렇다. 쓰긴쓰는데 뭔가 그냥 쓰는 기분이다.
성격상 100%는 아니더라도 80~90% 정도는 되어야 쓸때 아 이래서 쓰는구나를 체감하면서 쓰는데, 훅은...아직 나랑 덜 친한 기분이다. 아무 좀 뭔가 뿌듯함이 없다.
왜냐하면 잘 몰라서가 아닐까?
정리가 잘된 블로그를 통해 한번 정리하면서 왜 쓰는건지 정확히 이해하기로 했다.
그리고 공식문서를 확인하면서 정리하였다. 왜냐하면, 가끔 이상하게 해석해서 올린 글들을 확인했..ㅠ
나의 정리를 도와줄 블로그 출처:
https://defineall.tistory.com/900
내가 느끼는 훅: 편안하게 해준다. 내가 코딩할때, 편하게 해준다. 그런데, 왜그런지 모르겠다. 훅쓰면 편하다. '왜'를 알아야한다는 것을 알았다.
Hook, 이름부터 왜 '훅'인지는 알수없으나, 리액트 16.8 버전에서 새로 추가되었다 (생각보다 젊은 기술이네).
이상하게 역사를 알아야 할 것 같다. 등장배경? 이 바로 그것이다.
(1) Class 컴포넌트 와 Function 컴포넌트
아무튼 간단히 전문적으로 말하면 -> render props나 HOC(High order component, 고차 컴포넌트)와 같은 패턴으로 코드의 추적이 어렵다. 이렇게 계속 코드를 짤경우 wrapper hell을 겪게되고 (많은 레이어들로 둘러쌓인), 코드가 복잡해진다.
(내가 배우면서 사용했을때의 문제점으로 인하여 함수형으로 전환 되었다는 것을 알고나서 좀 신기했다.)
import React, { Component } from 'react';
class Example extends Component {
state = {
count: 0,
};
setCount(num) {
this.setState({
count: num,
});
}
render() {
const { count } = this.state;
return (
<div>
<div>
<p>You clicked {count} times</p>
<button
onClick={() => {
this.setCount(count + 1);
}}
>
Click Me!
</button>
</div>
</div>
);
)
}
export default Example;
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click Me!
</button>
</div>
);
}
export default Example;
클래스형은 보기만해도 숨이 턱턱 막힌다. this.이부분. 저것 보기만해도 싫다. 자바 할때부터 보기싫었다. 나만 그런가. 아무튼 함수형을 보면 뭔가 속이 뚫린다. 편하다. 굳이 저렇게 this.안해줘도 다 내장되어있으니까. render() -> return() 으로 바뀌긴 했지만, 뭔가 렌더 그대로 사용했으면 어떨까 라는 생각이 든다. 뭔가 더 뿌려준다는 느낌이 더 든다.
import React, { useState } from 'react';
funtion App() {
const [name, setName] = ('');
const [age, setAge] = (35);
const [coffee, setCoffee] = ('Latte');
}
export default App;
훅을 통하여 여러개의 state를 사용 하는 것도 가능한다.
같은 훅을 여러번 호출 가능하다.
최상위 에서만 훅을 호출해야 한다. 훅을 호출하는 순서는 항상 같아야 한다
export default function App(){
return {
<div>
// 불가능
<div>{const [value, setvalue] = useState()}</div>
</div>
}
}
export default function App(){
// useEffect Hook 내부에, 비동기 함수가 들어가므로 에러 발생
useEffect(async () => {
await Promise.resolve(1)
}, [])
return {
<div>
<div>Test</div>
</div>
}
}
내가 팀 프로젝트건, 혼자 VS code 켜놓고 코딩을 하던 제일 많이 쓰는 훅이 있다.
useState와 useEffect. 사실 정리를 하는 이유는, 어떤 훅들이 있는지 알려고 한거였는데, 처음부터 개념 잡으니까 확실히 도움이 된다.
state란 -> React에서 사용자의 반응에 따라, 화면을 바꿔주기(렌더링) 위해 사용되는 트리거역할을 하는 변수. React가 state를 감시하고, 바뀐 정보에 따른 화면을 표시해준다.
( state와 setState함수의 반환값을 비교 )
사용법.
import { useState } from "react";
// const [state, state변경함수] = useState(기본 state값);
const [isLoggedIn, setIsLoggedIn] = useState(false);
state를 변경하고싶다?
// 전에 만든 "isLoggedIn" state의 값을 true로 변경한다.
setIsLoggedIn(true);
// ** useState함수를 사용해 만든 "state 변경 함수"를 사용하여야 한다.
useEffect -> 비동기방식 -> render and paint 이후 실행. Paint 된 이후에 실행되서 화면의 깜빡임을 보게된다.
useLayoutEffect -> 동기방식(끝날때까지 리액트가 기다려줌) -> render된 후에 useLayoutEffect 실행되고 -> paint 한다. 화면깜빡임을 볼 수 없다. -> 레이아웃까지 보는데 시간 오래걸리니까 useEffect 권장.
// React에 기본적으로 내장되어 있는 useState와, useEffect 불러오기
import { setState, useEffect } from "react";
...
function App() {
const [data, changeData] = setState(false)
// useEffect(실행할 함수, 트리거가 될 변수) 또는 useLayoutEffect(실행할 함수, 트리거가 될 변수) 사용하면된다.
useEffect(() => {
if (data.me === null) {
console.log("Data changed!")
}
return () => console.log("컴포넌트 파괴, 언마운트 됨")
}, [data]);
// data변수가 바뀔때마다, react가 이를 감지해, 콘솔창에 "Data changed!" 출력
return (
<div>
<button value="적용" onClick={changeData(!data)} />
</div>
)
}
export default App;
간단한 예시일뿐. 실제로 사용해보면 장난아니다. 그런데 편하긴하다.
// newContext.js
import { createContext } from "react" // createContext 함수 불러오기
// context안에 homeText란 변수를 만들고, 공백("") 문자를 저장한다.
const newContext = createContext({
homeText: "",
})
// App.js
import React from "react";
import { View } from "react-native";
import Home from "./Home"; // 자식 컴포넌트 불러오기
import { newContext } from "./newContext"; // context 불러오기
export default function App() {
// context에 저장할 정보를 입력한다.
const homeText = "is Worked!"
// NewContext.Provider로 우리가 만든 context를 사용할 부분을 감싸준다.
return (
<newContext.Provider value={{ homeText }}>
<View>
<Home />
</View>
</newContext.Provider>
);
}
// Home.js
import React from "react";
import { Text, View } from "react-native";
import { useContext } from "react";
import { newContext } from "../newContext";
export default function Home() {
// useContext hook 사용해서, newContext에 저장된 정보 가져오기
const { homeText } = useContext(newContext);
// 불러온 정보 사용하기!!
return (
<View>
<Text>{homeText}<Text>
</View>
);
}
useMemo
Memoization : 과거에 계산한 값을 반복해서 사용할때, 그 값을 캐시에 저장하는 것
export default function App(){
const data = useMemo(()=> "data",[]);
// 데이터 변수는 의존성 배열 []에따라 선언된다. ( []사용시, 첫 렌더링 시에 1번만 선언 )
return <></>
}
useCallback
의존성을 사용해, 첫렌더링시에만 실행할 함수를 설정할 수 있다.
export default function App(){
const avatarPressed = useCallback(() => Alert.alert('avatar pressed.'), []);
return <></>
}
써본적 있는데... 이제 뜻을 제대로 알다니...하아...진짜 왜그럴까..
export default App(){
const viewRef = useRef(null)
// viewRef 객체에 있는 메소드를 사용한다.
function testFunc(){
viewRef.current?.메소드()
}
/// viewRef요소에, 해당 메모리 주소 전달
return <View ref={viewRef}>
<Text>Test</Text>
</View>
}
간단히 쓰여있긴한데... 더 찾아봐야겠다. 사용해본적은 있는데, 크게 인상적으로 막 주의깊게 본적은 없고 그냥 썼었다..
참고:
먼저 자식 컴포넌트와 자식 컴포넌트로 이루어진 부모 컴포넌트가 있다고 가정하자.
// Player.jsx
import React, { useRef } from "react";
import Audio from "./Audio";
import Controls from "./Controls";
function Player() {
const audioRef = useRef(null);
return (
<>
<Audio ref={audioRef} />
<Controls audio={audioRef} />
</>
);
}
export default Player;
useRef()를 사용하여 audoRef를 만들어서 Audio자식에 넘겨주고, Controls자식에는 audio prop으로 넘겨주고 있다.
Audio 자식이 ref prop을 Player 부모로부터 제대로 받으려면, forwardRef()함수를 사용하여야 한다. 아 이쯤되니까 무엇인가 이해가기 시작. 아 알겠다이제대충.
두번째 인자 ref로 넘어온다..
// Audio.jsx
import React, { forwardRef } from "react";
import music from "./music.mp3";
function Audio(prop, ref) {
return (
<figure>
<figcaption>Eyes on You (Sting) - Network 415:</figcaption>
<audio src={music} ref={ref}>
Your browser does not support the
<code>audio</code> element.
</audio>
</figure>
);
}
export default forwardRef(Audio);
이 외에도, useImerativeHandle, useReducer, useDebugValue 가 있다.
핵심적으로 많이 쓰이는 것들만 정리를 했다. 나머지는 공식문서를 보면서, 구글링을 하면서 연습을 해봐야겠다. 깃헙에서 하나 만들어서 사용해보고 있는데, 내가 이상하게 좀 공포증(?) 같은것이 있나보다. 뭔가 처음에 익숙하지 않으니까, 두려움이 앞선다. 우선 내지르고 코드를 짜봐야 실력이 좋아진다는 것은 코딩하면서 항상 느낀다. 열심히 잘 해봐야지!!