함수형 컴포넌트
- Hooks이 등장하기 전까지는 Class 기반으로 하는 클래스형 컴포넌트를 사용 → 클래스형 컴포넌트는 코드의 재사용이 어려우며 연관성이 없는 로직을 하나의 생명주기 메소드에서 구현해야하는 한계가 존재한다.
- 이러한 문제 해결이 가능하게 된 것은 Hooks이 등잠한 것이다.
- 현재 React에서 함수형 컴포넌트 + Hooks의 조합을 권장한다.
Hooks
useState
- 표현하자면 getStatus 와 setStatus이다.
- 간단하게 상태(Status)를 읽고 쓰는 것을 할 수 있게 제공해주는 것을 의미한다.
import React, {useState} from 'react';
import {Container} from '@mui/material'
import axios from 'axios';
export default function Reply(props) {
const[readOnly, setReadOnly] = useState(true);
const deleteReply = props.deleteReply
const deleteEventHandler = () => {
deleteReply(reply);
}
const turnOffReadOnly = () => {
if(login.mno == reply.mno){
setReadOnly(false);
}
}
const turnOnReadOnly = (e) => {
if(e.key === "Enter" || e.keyCode === 13){
console.log("turnOnReadOnly")
setReadOnly(true);
axios.put("/reply", reply).then(r => {
updateReply();
})
}
}
const delteBtnView = login.mno == reply.mno ?
<IconButton onClick = {deleteEventHandler}><DeleteOutlined/></IconButton>
: <div></div>
return (<>
<ListItem>
<ListItemText>
<InputBase style ={{width : '150px'}}inputProps= {{readOnly : readOnly}}
onClick = {turnOffReadOnly}
onKeyDown = {turnOnReadOnly}
type ="text"
rno = {reply.rno}
name = {reply.name}
value= {reply.rcontent}
multiline={true}
/>
</ListItemText>
<ListItemSecondaryAction>
{delteBtnView}
</ListItemSecondaryAction>
</ListItem>
</>)
}
- 코드가 무슨 코드인지는 이해할 필요가 없는데 주석 부분을 보면 이런식으로 setReadOnly() 할때마다 status의 상태는 맞게 변화하고 있다.
const[readOnly, setReadOnly] = useState(true);
- useState 선언하는 방법은 구조분해 방식인데, 여기서 구조 분해 방식이란 어떤 것을 복사한 이후에 변수로 '분해(destructurize)'해준다는 의미이며 아래와 같은 방식이다.
// 이름과 성을 요소로 가진 배열
let arr = ["Ga0", "Kwon"]
// 구조 분해 할당을 이용해
// firstName엔 arr[0]을
// surname엔 arr[1]을 할당하였습니다.
let [firstName, surname] = arr;
- 다시 말하자면 배열이나 객체를 변수로 분해하는 것을 의미한다.
- 기본 값이 읽기모드이다.setReadOnly(값) 값에 따라읽기모드 해제 및 적용을 수행한다.
- 다시 react.js예시 Reply를 보면 useState는 초기값으로 true를 가지며 setReadOnly를 통해 상태를 재설정하는 상태 관리 Hook이다.
useEffect
- useEffect Hook은 컴포넌트가 렌더링 된 이후에 수행해야 하는 작업이다.
- useEffect는 callback 함수와 dependency를 받는데 React는 useEffect의 callback 함수를 기억했다가, 컴포넌트가 렌더링 된 후에 함수를 실행한다.
let[pageInfo, setPageInfo] = useState({"cno" : 0, "page" : 1, "key" : '', "keyword" : ''})
useEffect (() => {
axios.get("/board", {params: pageInfo})
.then(res => {
console.log(res.data)
})
.catch(err => {console.log(err)})
}, [pageInfo])
- 해당 코드는 pageInfo(게시물 리스트 에 관련된) 정보가 바뀌었을 때마다 자동 렌더링을 하는 코드이다.
- useEffect는 의존성 배열을 받는데, 이 의존성 배열 내의 요소가 변할 때 마다 effect 함수를 실행한다.
- 의존성 배열에 빈 배열이 들어가 있으면 처음 컴포넌트가 렌더링되는 시점에만 effect 함수를 실행한다.
- 의존서 배열이 없다면 페이지가 렌더링 될 때마다 effect함수를 실행하기 때문에 비효율적이다.
→ 즉, useEffect는 컴포넌트가 렌더링 될 때마다 effect 함수를 실행하고 의존성 배열을 통해 선택적으로 그 시점을 관리한다.