오늘 내가 배운 것
1. React.Fragment
2. useRef
3. Custome Hook
1. React.Fragment
React를 처음 배울 때 컴포넌트 return에 최상위 엘리먼트는 1개여야 한다는 것을 설명한 적이 있다. 그때 모든 컴포넌트 대해서 `div`를 이용해서 감쌀 경우 원치 않은 div에 감싸지는 경우가 생긴다.
<div>
<div>컴포넌트 1-1</div>
<div>컴포넌트 1-2</div>
</div>
<div>
<div>컴포넌트 2-1</div>
<div>컴포넌트 2-2</div>
</div>
최상위 `div`를 React.Fragment로 감싸게 되면
<React.Fragment>
<div>컴포넌트 1-1</div>
<div>컴포넌트 1-2</div>
</React.Fragment>
<React.Fragment>
<div>컴포넌트 2-1</div>
<div>컴포넌트 2-2</div>
</React.Fragment>
코드를 작성할 때는 <React.Fragment> 태그가 있지만 실제로 출력되는 엘리먼트 요소는
<div>컴포넌트 1-1</div>
<div>컴포넌트 1-2</div>
<div>컴포넌트 2-1</div>
<div>컴포넌트 2-2</div>
로 생략되어 나온다.
<React.Fragment>는 <></> 빈 상태로 작성해서 간단하게 사용할 수 있다.
이를 활용해서 컴포넌트를 만들 때 default로 넣고 사용하는 경우가 많다.
return (
<>
<div>컴포넌트 1-1</div>
<div>컴포넌트 1-2</div>
<div>컴포넌트 2-1</div>
<div>컴포넌트 2-2</div>
</>
)
2. useRef
React Hook 함수중 `useRef`를 이용하여 DOM 요소를 선택하고 싶을 때 사용할 수 있다.
예를 들어 input 태그를 이용해서 해당 input에 focus()를 이용하고 싶을 때 vanilla JS에서는
const userId = document.querySelector("#userId")
userId.focus()
위와 같이 사용했었다.
리액트에서는 함수형 컴포넌트를 사용할 때 위와 같은 방법이 아닌 useRef()를 이용하여 작성한다.
const Ref = () => {
const userId = useRef(null)
console.log(userId, "최소 렌더시 생성")
const handleSubmit = (e) => {
e.preventDefault()
userId.current.value = ""
userId.current.focus()
console.log(userId, "submit 발동시")
}
useEffect(() => {
console.log(userId, "Mount시")
}, [])
return (
<>
<form onSubmit={handleSubmit}>
<input type="text" id="userId" ref={userId} />
<input type="text" id="userPw" />
<button type="submit"> 확인</button>
</form>
</>
)
}
이를 이용하여
userId.current.focus()
submit 이벤트 발동 시 focus()을 할 수 있다.
사진을 보면 최초 렌더링을 할 때 userId의 값은 비어있었다.
이후 마운트가 되면서 userId의 상태값이 바뀌고 이때 userId의 값이 대입된 것을 확인할 수 있다.
어느 시점에 값이 할당되어 사용이 가능한지를 알고 적용할 수 있어야 한다.
3. Custom Hook
custom hook을 만드는 가장 큰 목적은 중복된 코드를 제거하기 위해서 만든다.
만약 input 박스가 여러 개 있는 `회원가입 Form`을 리액트를 이용해서 만들 때, 상태를 관리하기 위해서 같은 역할을 하는 함수들이 많아지게 된다.
const [userid, setUserid] = useState("")
const [userpw, setUserpw] = useState("")
const [userNick, setUserNick] = useState("")
const [userName, setUserName] = useState("")
.
.
.
const handleChange = (e) =>{
e.preventDefault()
setUserid(e.target.value)
}
const handleChange2 = (e) =>{
e.preventDefault()
setUserpw(e.target.value)
}
.
.
.
이러면 변수도 많아지고 이에 따라 이벤트 이름을 공통적으로 짓게 되면 나중에 유지보수, 중복된 코드가 많아지게 된다.
그래서 함수로 따로 관리하여 조금 더 간결하게 코드를 작성할 수 있다.
// 컴포넌트
import useInput from "./useInput"
const obj = useInput("")
const obj2 = useInput("")
return (
<>
<form onSubmit={handleSubmit}>
<input type="text" id="userId" ref={userId} {...obj} />
<input type="text" id="userPw" ref={userPw} {...obj2} />
<button type="submit"> 확인</button>
</form>
</>
)
//
// useInput
import React, { useState } from "react"
const useInput = (inital) => {
const [value, setValue] = useState(inital)
const onChange = (e) => {
setValue(e.target.value)
}
return {
value,
onChange,
}
}
export default useInput
useInput이라는 함수 하나로 상태를 관리할 수 있기 때문에 중복코드를 제거할 수 있다는 장점이 있다.
그리고 useInput()의 매개변수로 초기 value 값을 설정할 수 있다.
엘리먼트 속성의 {...obj} 부분을 보면 obj는 useInput()인데 return 값이 객체 형태이다.
JS문법을 이용하면 `...` 전개구문(스프레드 연산자)을 이용해서 객체 안에 요소를 다 사용할 수 있다.
그렇기 때문에
const obj = useInput("") // {value, onChange}
return <input type="text" id="userId" ref={userId} {...obj} />
//의 내용은 아래
return <input type="text" id="userId" ref={userId} value="" onChange={() => {}} />
// 와 같다.
위에 input 내용과 아래의 input 내용은 같다.
'시작 > TIL(Today I Learned)' 카테고리의 다른 글
230303 - React - npm과 npx, prop (0) | 2023.03.04 |
---|---|
230302 - React - CSS 적용하기 (0) | 2023.03.03 |
230228 - React - Functional Component and Hook (함수형 컴포넌트와 Hook) (0) | 2023.02.28 |
230228 - Webpack (웹팩) - hot reloading (0) | 2023.02.28 |
230227 - Webpack ( 웹팩 ) (0) | 2023.02.28 |
댓글