훅(HOOK) 이란?
리액트 컴포넌트는 클래스형 컴포넌트(Class component)와 함수형 컴포넌트(Functional component)로 나뉜다
리액트 훅은 새로운 기능으로 React 16.8버전에 새로 추가된 기능으로 함수형태의 컴포넌트에서 사용되는 몇 가지 기술을 Hook이라고 부른다 (useState, userEffect 등)
리액트 훅은 함수형 컴포넌트가 클래스형 컴포넌트의 기능을 사용할 수 있도록 해주는 기능이다
Hook의 규칙
1️⃣ 최상위에서만 Hook을 호출해야 한다
2️⃣ 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안 된다
3️⃣이 규칙을 따르면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로
Hook이 호출되는 것이 보장된다
4️⃣ 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다
보충 설명을 덧붙이자면 useState나 useEffect 같은 훅들이 여러 번 사용될 수 있는데,
리액트는 이 훅들을 호출되는 순서대로 저장해 놓는 특징이 있다
(👉매 랜더링마다 순서대로 훅 호출 )
그렇기 때문에 조건문이나 반복문 안에서 훅을 쓰게 되면 훅은의 호출 순서가 꼬일 수 있기에
항상 리액트 함수 최상위 레벨에서만 호출해야 한다는 것이다
반드시 알아야 할 기본 훅 ⭐
1️⃣ useState
useState ( 초기값 ) : 배열 반환
✅ 첫번째 배열의 요소에는 현재값을, 두번째 요소는 상태를 변경하는 함수(setter) 를 반환한다
const [data, setData] = useState('초기값')
2️⃣ useEffect
useEffect ( 실행시킬 콜백함수, 값에 따른 렌더링 지정 )
userEffect의 첫번째 매개변수는 실행시킬 콜백함수,
두번째 매개변수는 배열[ ]을 사용하여 특정값이 update 될 때만 실행시켜 줄 수 있다
useEffect( )는 컴포넌트의 라이프 사이클을 다루며
리액트 컴포넌트가 mount, mount이후, unmount 때마다 특정작업을 수행한다
1️⃣ mount 이후 - 컴포넌트가 마운트 됨
( 즉 컴포넌트의 첫번째 렌더링이 마치면 호출되는 메서드 )
클래스형 componentDidMount( ) 대체
함수형 훅
useEffect( () => {
console.log(`렌더링완료`);
});
⚠️ 오늘의 오 마이 미스테이크!
useEffect = ( ) => {
// 화살표 함수처럼 작성하는 게 익숙해져서 실수함(이러면 난리남...알고 싶지 않았음 나도 ㅎ)
console.log(`렌더링 완료`);
};
만약 mount 이후에 업데이트 될 때는 실행되지 않으려면, 두번째 매개변수 배열를 주면 된다
useEffect( () => {
console.log(`처음만 실행됩니다`);
}, []);
2️⃣ update 이후 - 특정값에 의해 컴포넌트가 업데이트 되고 난 후 발생
클래스형 componentDidUpdate( ) 대체
함수형 훅
const HookEffect = () => {
//useState
const[name, setName] = useState('');
const handleName = (e) => {
setName( e.target.value );
}
//특정값이 업데이트 될 때만 실행해주려면 두번째 매개변수에 값을 state값을 지정합니다
useEffect( () => {
console.log(`name이 업데이트 시 실행됩니다`)
}, [name]);
return (
<div>
이름:<input type="text" onChange={handleName}/><br/>
이름:{name}
</div>
)
}
export default HookEffect;
3️⃣ unmount직전 - 컴포넌트가 화면에서 사라지기 직전에 호출
클래스형 componentWillUnMount() 대체
함수형 훅
const HookEffect = () => {
//useState
const[name, setName] = useState('');
const handleName = (e) => {
setName( e.target.value );
}
//useEffect
useEffect( () => {
console.log(`name이 업데이트 시 실행됩니다`)
//unmount이후 실행됩니다.
return () => {
console.log(`unmount에 실행됩니다.`);
}
}, [name]);
return (
<div>
이름:<input type="text" onChange={handleName}/><br/>
이름:{name}
</div>
)
}
export default HookEffect;
한번에 보는 useEffect 😉
3️⃣ 특정 태그에 이름달기 - useRef ( )
const사용할이름 = useRef (null);
이벤트를 사용하다 보면 특정 태그에 접근해서 핸들링 하는 경우가 생긴다
arrow function에 event 매개변수를 이용해서, 자신 태그에는 접근할 수 있지만 다른태그는 핸들링 하기가 어렵다
이런 경우 useRef( ) 훅을 이용해서 특정태그에 이름을 지정하고 핸들링 할 수 있다
const HookRef = () => {
//useState
const [form, setForm] = useState({data: '', result: '' });
//useRef
const inputTag = useRef(null);
//인풋핸들링
const handleChange = (e) => {
setForm( {data :e.target.value} ); //인풋값이 변할때마다 data변수 변화
}
//버튼핸들링 - 클릭시 state는 변경하고, input태그에 포커스
const handleClick = (e) => {
setForm( {data: '', result: form.data})
//useRef의사용 - current로 ref의 현재태그에 접근가능
inputTag.current.focus()
}
return (
<div>
할일: <input type="text" value={form.data} onChange={handleChange} ref={inputTag} />
<button type="button" onClick={handleClick}>등록하기</button>
<br/>
결과: {form.result}
</div>
)
}
export default HookRef;
부가적으로 알면 좋은 훅
✅ useReducer
useState의 사용을 외부에서 사용할 수 있게 해주는 훅( state의 변경을 외부에서 제어 )
const [현재값, 리듀서를 업데이트할 수 있는 함수] = useReducer(외부에서 사용할 리듀서함수, 리듀서의 초기값)
Hook(useEffect, useState, useRef) 으로 다음의 조건을 충족시켜보렴 👩💻
첫 번째 실습
1️⃣ 컴포넌트가 마운트된 이후 한번만 id태그에 포커스를 주기
2️⃣ id, pw는 state로 관리한다
로그인 버튼 클릭시 공백이라면 공백인 태그에 포커스를 주기
로그인 버튼 클릭시 공백이 아니라면 경고창으로 id와 pw를 출력
[ 전체 코드 ]
import { useEffect, useRef, useState } from "react";
const HookEffect_again = () => {
/*
1.컴포넌트가 마운트된 이후 한번만 id태그에 포커스를 준다
2.id, pw는 state로 관리한다
로그인 버튼 클릭시 공백이라면 공백인 태그에 포커스를 주세요
로그인 버튼 클릭시 공백이 아니라면 경고창으로 id와 pw를 출력해주세요
*/
//컴포넌트가 마운트된 이후 딱 한 번 id태그에 포커스 주기
useEffect (() => {
inputId.current.focus();
},[]);
const inputId = useRef(null);
const inputPw = useRef(null);
//id, pw state로 관리
const [data, setData] = useState({id:'', pw:''});
//id, pw창에 값이 입력되었을 때, 사용자가 입력한 값을 state에 저장 => 태그의 value에 값을 넣어야 화면 출력
const handleChange = (e) => {
setData({...data, [e.target.name]: e.target.value});
// console.log(e.target.value);
// console.log(setData);
}
//로그인 버튼 클릭
const handleClick =() =>{
if(inputId.current.value === ''){
inputId.current.focus();
}else if(inputPw.current.value === ''){
inputPw.current.focus();
} else{
alert(`아이디: ${data.id}, 비밀번호: ${data.pw}`);
}
}
return (
<div>
<h3>훅 실습</h3>
<input type="text" name="id" placeholder="아이디" value={data.id} onChange={handleChange} ref={inputId} /><br />
<input type="password" name="pw" placeholder="비밀번호" value={data.pw} onChange={handleChange} ref={inputPw} /><br />
<button onClick={handleClick}>로그인</button>
</div>
)
}
export default HookEffect_again;
두 번째 실습
실습(할 일 목록 만들기)
1️⃣ state { todo : ' ', list : [ ] }로 관리하기
2️⃣ 할 일 목록을 작성하고, 클릭시 list에 인풋의 입력값을 추가하고 map을 통해서 화면을 그린다
3️⃣ 등록된 이후에는 ref를 활용해서 input태그에 포커싱을 준다
import { useRef, useState } from "react";
const HookQ2_mine = () => {
// 1. state {todo:'', list:[]}로 관리하기
const [data,setData] = useState({todo:'', list:[]});
const inputId = useRef(null);
//2. 할 일 목록을 작성하고 (이벤트 객체 이용)
const handleChange = (e) => {
setData({...data, [e.target.name]: e.target.value});
}
// 클릭시 list에 인풋의 입력값을 추가하고 map을 통해서 화면을 그린다
const handleClick = () => {
let newList3 = data.list.concat(data.todo);
setData({...data, ['todo']:'' , ['list']:newList3});
inputId.current.focus(); // 등록된 이후 포커싱
}
//화면에 출력
const newData = data.list.map((item, index) =>
<li key={index}>
{item}
</li>
)
//엔터키 처리
const handlePress =(e) =>{
if(e.keyCode == 13){
handleClick();
}
}
return(
<div>
<h3>ref로 할 일 목록 만들기</h3>
<input type="text" name="todo" onChange={handleChange} onKeyDown={handlePress} placeholder="할 일 목록" value={data.todo} ref={inputId}/>
<button onClick = {handleClick} >등록하기</button>
<ul>
{newData}
</ul>
</div>
)
}
export default HookQ2_mine;
'React' 카테고리의 다른 글
[React] 라우터 총정리본 (이것만 보면 반은 먹고 들어간다! ) (0) | 2023.01.25 |
---|---|
[React] 라우터 (useNavigate, Navigate, Link 등) (1) | 2023.01.20 |
[React] state와 이벤트 핸들링 (0) | 2023.01.16 |
[React] 리액트의 Components와 props (0) | 2023.01.15 |
[React] JSX 문법 알고 싶으면 이리온 : ) (0) | 2023.01.15 |