[TIL # 57] React Basic (2)

Yejin Yang·2022년 7월 27일
0

[TIL]

목록 보기
56/67
post-thumbnail

[수업 목표]

  1. React 의 생명 주기에 대해서 이해한다.
  2. React 로 간단한 타이머를 만들어본다.
  3. React 로 Login 화면을 만들어본다.

⭐️ 새롭게 안 사실

리액트의 생명 주기(Life Cycle)

컴포넌트가 표시되고 사라지는 순간까지를 하나의 생명 주기라 한다.

크게 세 가지로 시점을 나눌 수 있다.

  • mount (컴포넌트가 표시될 때)
  • update (컴포넌트 내부의 요소가 업데이트될 때)
  • unmount (컴포넌트가 사라질 때)

mountupdateunmount

useEffect

useEffect가 하는 일
useEffect Hook을 이용하여 우리는 React에게 컴포넌트가 렌더링 이후에 어떤 일을 수행해야하는 지를 말합니다. React는 우리가 넘긴 함수를 기억했다가(이 함수를 ‘effect’라고 부릅니다) DOM 업데이트를 수행한 이후에 불러낼 것입니다. 위의 경우에는 effect를 통해 문서 타이틀을 지정하지만, 이 외에도 데이터를 가져오거나 다른 명령형(imperative) API를 불러내는 일도 할 수 있습니다.

useEffect를 컴포넌트 안에서 불러내는 이유
useEffect를 컴포넌트 내부에 둠으로써 effect를 통해 count state 변수(또는 그 어떤 prop에도)에 접근할 수 있게 됩니다. 함수 범위 안에 존재하기 때문에 특별한 API 없이도 값을 얻을 수 있는 것입니다. Hook은 자바스크립트의 클로저를 이용하여 React에 한정된 API를 고안하는 것보다 자바스크립트가 이미 가지고 있는 방법을 이용하여 문제를 해결합니다.

useRef

React 컴포넌트는 기본적으로 내부 상태(state)가 변할 때 마다 다시 랜더링(rendering)이 된다. 다시 랜더링 되어도 동일한 참조값을 유지하고 싶을때 이용하는 것이 useRef이다.

  1. 활용법 - 요소 가져오기
    getElementById 등과 동일한 역할을 한다고 생각하면 된다.
import React, { useRef } from 'react'

function Refs() {
  const a = useRef()

  const keyHandler = () => {
    console.log(a.current.value)    
  } 

  return (
    <>
        <input ref={a} onKeyDown={keyHandler}/>
    </>
  )
}

export default Refs
  1. 활용법 - 재렌더링 되지 않는 변수를 만들 때
import React, { useRef } from 'react'

function Refs() {
  const a = useRef(0)

  const keyHandler = () => {
    console.log(a.current + 1)    
  } 

  return (
    <>
        <p>{a.current}</p>
        <button onClick={keyHandler}>버튼!</button>
    </>
  )
}

export default Refs

로그인 화면에서, 아이디 & 비밀번호 한번에 처리하기

import React, { useState, useEffect } from 'react'

function Login() {
  const [userInput, setUserInput] = useState({id: '', pw: ''})

  const onUserInputChange = (e) => {
    const { name, value } = e.target
    setUserInput({...userInput, [name]:value})
  }

  const doLogin = () => {
    alert('로그인 완료!')
  }

  return (
    <div>
        <input 
    	placeholder="아이디를 입력하세요" 
    	value={userInput.id} 
		name="id" 
		onChange={onUserInputChange} />
          
        <input 
		placeholder="비밀번호를 입력하세요" 
		type="password" 
		value={userInput.pw} 
		name="pw" 
		onChange={onUserInputChange} 
		onKeyDown={(e) => {if(e.key==="Enter"){doLogin()}}} />

        <button onClick={doLogin}>
        로그인
        </button>
    </div>
  )
}

export default Login
  • value값에서 useStateid에 접근하기위해 점 표기법 사용
  • onChange 에 들어갈 함수에서 스프레드 연산자를 사용해서 기존의 input 객체를 복사 하기
  • name 키를 가진 값을 value 로 설정

📌 꼭 기억할 것

useEffect 사용법

  1. mount (컴포넌트가 표시될 때)
useEffect(컴포넌트가 표시될 때 실행할 함수, [여기는 빈 대괄호입니다]);
  1. update (컴포넌트 내부 요소가 업데이트될 때)
useEffect(오른쪽 리스트에 적은 요소들이 업데이트되는 시점에 실행할 함수, [업데이트 되는지 지켜볼 변수/State]);
  1. unmount (컴포넌트가 사라질 때)
useEffect(() => {return () => 컴포넌트가 사라질 때 실행할 함수})

useEffect 활용법

const [isLoaded, setIsLoaded] = useState(false)

삼항연산자 활용
{조건문 ? 참일때 실행될 부분 : 거짓일때 실행될 부분} 의 형태

 <div>
      {isLoaded ? <>로딩완료!</> : <>로딩 중</>}
 </div>

React 의 이벤트 처리

onClick: 클릭하면 특정한 함수가 실행되도록 하기 위한 이벤트 핸들러
onChange: input 태그에서 내부 내용이 바뀔 때 실행될 함수를 지정
onFocus: input 태그에 포커싱되었을 때 실행될 함수를 지정
onBlur: 포커스가 풀렸을 때 실행될 함수를 지정할 수 있습니다.
onKeyDown: 키를 눌렀을 때 실행되는 함수를 지정

*onKeyPress 는 사용을 지양한다.

spread operator 사용 시 주의점

...userInput

...userInput 과 같이 ... 을 사용하는 것을 spread operator 라고 한다. 특정한 상태 내부의 값들을 펼쳐서 담고자 할 때 쓰는 문법이다.

spread operator 는 내부의 값이 어떤 것이 있는지 명확한 경우에만 사용한다. 명확하지 않은 경우에는 아예 사용하지 않는 것이 좋다.


📚 실습 풀어보기

유저가 시간초를 설정할 수 있는 타이머 만들기

[세부사항]

  1. onChange 를 활용해서, 유저가 입력한 값 그대로 타이머에 반영되도록 해보세요.
  2. ‘타이머 설정’ 이라는 버튼을 눌러야만 유저에게 표시되는 시간초가 바뀌도록 해보세요. (useState, onClick 활용 혹은 useRef 활용)
  3. 버튼을 마우스로 누르지 않고, 엔터만 입력해도 타이머 시간이 설정되도록 해보세요. (onKeyPress 활용)

[해답 및 해석]

import React, { useState, useRef, useEffect } from 'react'

function Timer() {
  const [seconds, setSeconds] = useState(60)
  const [isClicked, setIsClicked] = useState(false)
  const inputRef = useRef()

  // Enter키를 누르면 inputHandler 함수 실행
  const inputHandler = () => {
    // ref는 객체이며 current 프로퍼티를 가지고 있다.
    // 객체를 통해 DOM에 직접적인 접근이 가능하다 current.value
    const { value } = inputRef.current
    setSeconds(value)
  }

  useEffect(() => {
    if (isClicked) {
      const countDown = setTimeout(() => {
        if (seconds > 0) {
          // 초가 0보다 크면, 1을 감소시킨다.
          setSeconds(seconds - 1)
        } else if (seconds === 0) {
          // 만약에 초가 0이 되면, 해당 함수가 실행되는 걸 멈춘다.
          clearTimeout(countDown)
        }
      }, 1000)
      // 페이지에서 벗어나면, 해당 함수도 이제는 작동하지 않도록 없애준다.
      return () => clearTimeout(countDown)
    }
    // seconds, isClicked 가 변하는 것을 감지한다.
    // 타이머 시작으로 인해 isClicked가 변하고 true값이 되어 조건문 통과
  }, [seconds, isClicked])

  return (
    <div>
      <input
        ref={inputRef}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            inputHandler()
          }
        }}
      ></input>
      <button onClick={inputHandler}>타이머 설정</button>
      <h1>우리의 타이머</h1>
      <h1>{seconds}</h1>
      <button onClick={() => setIsClicked(true)}>타이머 시작</button>
      <button onClick={() => setIsClicked(false)}>타이머 중지</button>
    </div>
  )
}

export default Timer
profile
Frontend developer

0개의 댓글