[카테캠] FE week 9 (2)

werthers·2023년 6월 7일
0

카카오테크캠퍼스

목록 보기
11/16
post-thumbnail

리액트로 구현하기

  • Create React App 을 통해 코드를 실행할 수 있는 환경 설정을 한다.
  • vanilla JS로 구현했던 로직을 바탕으로 react로 변경하며 구현한다.

1. 컴포넌트화

  • 컴포넌트 단위로 함수를 묶고 기능별로 구분하여 재활용이 가능한 코드를 만든다.
  • 각각의 .jsx 파일에 form footer 등 기능별 jsx 코드를 분리하여 App.js 파일을 간결하게 만든다.

재활용 가능한 코드로 만들어 중복 기능 함수 제거

form 에서 input 부분(아이디, 비밀번호, 비밀번호 확인 입력칸)은 각각 id label type placeholder 를 제외한 모든 부분이 같기 때문에 4개의 변수를 가져와 하나의 컴포넌트에서 재활용하여 사용할 수 있다.

또한, 한 번에 모든 form에 효과를 주거나 제어를 할 경우 컴포넌트 하나로 컨트롤 할 수 있다는 장점이 있다.

<FormInput
                id={'id'}
                label={'아이디'}
                inputProps={{
                    type: 'text',
                    placeholder: '아이디를 입력해주세요.',
                }}
            /> //FormInput로 재사용하여 변수로 각각 입력창 대응

2. autofocus

컴포넌트화 된 FormInputid 변수가 'id' 일 경우에 오토 포커스 되어야 한다.

  1. props에 id를 넘겨주는 Form 컴포넌트에서 autoFocus:true 를 추가한다.
<FormInput
                id={'id'}
                label={'아이디'}
                inputProps={{
                    type: 'text',
                    placeholder: '아이디를 입력해주세요.',
                    autoFocus: true, //id에만 추가
                }}
            />
  1. useEffect를 사용하여 특정 시점(의존성 부여)에 id에 포커스가 가도록 한다.
//useRef : DOM을 사용할 수 있게 해준다.	
	const idRef = useRef(null) 

    useEffect(() => { 
        if (id === 'id') idRef.current.focus()
    }, [])
//input 태그에 ref={idRef} 속성을 부여하고 사용 !

3. 제어 컴포넌트, 비제어 컴포넌트

  • 제어 컴포넌트 : React에 의해 값이 제어되는 폼 엘리먼트
  • 비제어 컴포넌트 : React에 의해 값이 제어되지 않는 폼 엘리먼트
  • 폼 엘리먼트 : Form을 구성하는 사용자 입력 기반 DOM 내부 상태를 가지는 엘리먼트 (input 등)

일반적인 DOM 엘리먼트는 사용자 입력이 아닌 React에서 state로 상태를 관리하고 그 상태를 바탕으로 렌더링한다.

폼 엘리먼트의 valueprops 으로 관리한다면 제어 컴포넌트로 사용하는 것이다. (useState 사용)

언제 무엇을 사용하는가 ?

  • 제어 컴포넌트를 사용하면 React에서 실시간 렌더링을 보장할 수 있다.
  • Form이 간단하고 실시간으로 이루어져야하는 작업이 없다면 비제어 컴포넌트를 사용하는 것이 효율적이다.

제어 컴포넌트의 상태(state)를 어떤 레벨에서 관리할 것인가?

  • 어떤 범위에서 상태를 참조하고 있는지에 따라 Form의 상태를 넓게 혹은 좁게 관리해야할 수 있다.
  • 넓은 상태 범위에서 참조한다면 데이터 업데이트시 많은 컴포넌트에서 재 렌더링이 발생할 수 있기 때문에 상황에 맞게 제어/비제어 컴포넌트를 사용하는 것이 효율적인 코드 관리

4. 유효성 검사

Form, FormInput 컴포넌트를 분리했기 떄문에 App.js에서 state를 만들어 보낸다면 Form 컴포넌트는 사용하지 않는 상태를 자식과 부모의 징검다리로 연결하기 위해 참조해야 하는데, 이 과정이 반복되는 것을 prop drilling 이라고 한다.

컴포넌트가 복잡해지고 사용하지 않는 참조를 해야하기 때문에 비효율적이므로 전역으로 사용하는 useContext를 사용하여 구현한다.

//App.js에서 context 생성
const initFormData = { 
    id: '',
    pw: '',
    confirmPw: '',
}
export const FormContext = createContext({ //export로 다른 컴포넌트에서 접근 가능
    formState: initFormData,
    setFormData: () => {},
})

// **************<FormContext.Provider value={{ formData, setFormData }}> //형태로 App함수 만들기

//FormInput.jsx에서 REGEX, MSG, check 함수 등 만들고 return**************

5. 입력 확인 모달 창

  • 가입하기 버튼에 클릭 이벤트 발생 시 modalshowModal, close 되기 위해서는 전체 화면을 제어하는App 에서 useRef 를 사용하여 넘겨준다.
  • React에서 ref를 바로 전달 받을 수 없기 떄문에 forwardRef를 사용하여 전달 받는다.
  • Modal.jsx 에서 useContextid, pw 정보를 가져온다. (전역)
  • 또한 가입하기 버튼이 있는 컴포넌트인 Form.jsx 에서도 modalRef 를 참조하여 클릭시 showModal 메소드를 호출 할 수 있도록 만든다. (이 때 참조하는 값 modalRef는 이름이 ref 가 아니기때문에 forwardRef 처리를 하지 않아도 된다.
//App.js
function App() {
	const modalRef = useRef(null)
	...
	<Form modalRef={modalRef}/>
	...
	<Modal ref={modalRef}/>
//Modal.jsx

const Modal = forwardRef((props, ref) => //ref 전달 시 forwardRef로 전체 감싸기
{ ...
	const { formData } = useContext(FormContext) //전역에 있는 id, pw 정보 가져오기
	const handleClick = (type) => {
		ref.current.close() //modal 창 닫기
	  type === 'increase' && window.alert('가입되었습니다') //가입 시 알림 창
	return (
				...
				{formData.id} //id 부분에 id를 innerText로 삽입
		)
}
//Form.jsx
const Form = ({modalRef}) => { //가입하기 클릭 시 showModal 
	const handleSubmit = (e) => {
			e.preventDefault()
			const isValid = Object.valuse(errorData).every(
				(value) => value === true //error 없을 시
			)
			isValid && modalRef.current.showModal()
		}
	return (
		...
		<input //가입하기
			type="submit"...onClick={handlesubmit}/>
)}
		

6. 폰트 사이즈 조절

  • useEffect useState 를 사용하여 버튼 클릭시 의존적으로 상태를 변경하고 반영하도록 만든다.
//FontSizeControl.jsx
const [fontSize, setFontSize] = useState(getHtmlFontSize())
    const handleClick = (flag) => {
        if (flag === 'increase') setFontSize((prev) => prev + 1)
        else setFontSize((prev) => prev - 1)
    }
    useEffect(() => {
        $html.style.fontSize = fontSize + 'px'
    }, [fontSize])
//button 속성 부분
				<button		onClick={() => handleClick('increase')}
                disabled={fontSize >= MAX_FONT_SIZE}> </botton>

7. 개선점 파악과 react-hook-form

chrome 확장 프로그램 react developer tool로 렌더링 횟수를 알아볼 수 있다. (효과적인지 아닌지)

  • React Hook Form 라이브러리의 도움을 받아 성능을 효율적으로 관리할 수 있다.
profile
Hello World !

0개의 댓글