1. React Hooks

이준구·2024년 1월 30일
0

React

목록 보기
5/13
post-thumbnail

useState란


형태: const [state, setState] = useState(initialState);

  • 구조분할 할당을 사용
  • state를 변수로 사용, setState를 이용해서 state 값을 수정
  • useState로 원시데이터가 아닌 데이터를 변경할때는 불변성을 유지해야 한다.

불변성이란


일반 사용법과 함수형 업데이트 방식

1) 일반 사용적인 방식
setState(number + 1);

2) 함수형 방식
setState(() => {});


3) 두 방식의 차이점

import { useState } from "react";

const App = () => {
  const [number, setNumber] = useState(0);
  return (
    <div>
	  {/* 리액트는 성능을 위해 setState()를 단일 업데이트(batch update)로
          한꺼번에 처리할 수 있다.
          불필요한 리-렌더링을 방지(렌더링 최적화)하기 위해 
          현재 버튼을 누르면 1씩 증가하게 되는 걸 볼 수 있다.  */}
      
      <div>{number}</div> 
      <button
        onClick={() => {
          setNumber(number + 1); // 첫번째 줄 
          setNumber(number + 1); // 두번쨰 줄
          setNumber(number + 1); // 세번째 줄
        }}
      >
        버튼
      </button>
    </div>
  );
}

export default App; 

import { useState } from "react";

const App = () => {
  const [number, setNumber] = useState(0);
  return (
    <div>
			{/* 현재 상태(prev)를 가져와 함수 형태로 실행하여 각각 처리한다.
                버튼을 누르면 3씩 증가된다. */}
      <div>{number}</div>
      <button
        onClick={() => {
          setNumber((previousState) => previousState + 1);
          setNumber((previousState) => previousState + 1);
          setNumber((previousState) => previousState + 1);
        }}
      >
        버튼
      </button>
    </div>
  );
}

export default App;




useEffect란

리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 때 사용한다.

  • useEffect는 화면에 컴포넌트가 mount 또는 unmount 됐을 때 실행하고자 하는 함수를 제어하게 해주는 훅이다.
  • 의존성 배열을 통해 함수의 실행 조건을 제어할 수 있다.
  • useEffect 에서 함수를 1번만 실행시키고자 할때는 의존성 배열을 빈 배열로 둔다.

    어떤 컴포넌트가 화면에 보여졌을 때 내가 무언가를 실행하고 싶다면? 또는 어떤 컴포넌트가 화면에서 사라졌을 때 무언가를 실행하고 싶다면? useEffect를 사용

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

function UseEffect() {
  const [value, setValue] = useState("");
  
  
  useEffect(() => {
     console.log(`hello useEffect: ${value}`); 
    
     //return문을 함수로 선언하면 해당 컴포넌트가 종료될 시에 실행된다.
    return () => {
        console.log("컴포넌트가 종료될 시 실행된다.!!")
    }
    })
  
  return (
    <>
    <input value={value} onChange={(event) => setValue(event.target.value)}></input>
    
    </>
    
  )
} 

  // 해석
  // 1. input에 값을 입력
  // 2. value, 즉 state가 변경
  // 3. state가 변경될 당시 ==> 컴포넌트가 리-랜더링됨
  // 4. 리랜더링 ==> useEffect 실행
  // 즉, 값을 입력할 때마다 useEffect가 실행되는 걸 볼 수 있다.
  // 여기서 특정 값이 변경될 때만 useEffect를 실행하게 하려면
  // 의존성 배열(dependency array)을 넣으면 된다.


의존성 배열(dependency array)란

:특정 조건의 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행하게 한다.

 //위의 코드에서 useEffect() 부분만 가져왔다.
  useEffect(() => {
   console.log(`hello useEffect: ${value}`); 
  
  return () => {
      console.log("컴포넌트가 종료될 시 실행된다.!!")
  }
  },[])  // []이 부분이 의존성 배열이다.

//의존성 배열이 빈 배열인 경우
// useEffect는 처음에 딱 한번만 실행되고 그 이후로는 어떤일이 일어나도 실행되지 않는다.
//의존성 배열에 값이 있을 경우
// 배열의 값이 state 될때마다 실행된다.
// 현재 배열에 [value] 값을 넣는다면 input 태그에 값을 입력될 때마다 작동 되는 걸 볼 수 있다.

useRef(reference)란

  • DOM 요소에 접근할 수 있도록 도와주는 역할로써 화면이 렌더링 되자마자 특정 input 태그가 focusing이 돼야 하는 경우 사용
  • ref 초기값 : { current: '' } 형태

state와 비슷한 역할이지만 서로 간의 차이점이 존재

  • useState는 변화가 일어나면 리-렌더링이 일어나 내부 변수들이 초기화된다.
  • useRef는 한 번 저장된 값은 렌더링을 일으키지 않으며 컴포넌트가 렌더링 되더라도
    ref 값은 unmount 전까지 값을 유지한다.
  • useState는 리-렌더링이 꼭 필요한 값을 다룰 때 쓰면 된다.
    ex) 버튼 클릭시
  • useRef는 리-렌더링을 발생시키지 않는 값을 저장할 때 사용한다.
    ex) 렌더링 되자마자 특정 input이 focusing 돼야 한다면 useRef를 사용한다.
import React, { useEffect, useState } from 'react'
import { useRef } from 'react';
function UseRef() {

const [id, setId] = useState("");
const [password, setPassword] = useState("");
const idRef = useRef("");
const pwRef = useRef("");


//idRef.current.focus();    
//함수 컴포넌트의 바디 외부에 있으므로 React의 렌더링 주기와 무관하게 동기적으로 실행됩니다. 
//이것은 React의 규칙에 위배되며, 해당 DOM 요소가 마운트되기 전에 focus() 메서드가 호출되므로 오류가 발생

// 화면이 렌더링 될 때, 어떤 작업을 하고싶다: useEffect
// 현재 id를 useState로 선언하여 id의 값이 변경될 때마다 랜더링이 되는 걸 볼 수 있다.
// 그래서 아래의 useEffect 부분은 id가 변경될 때마다 실행되는 걸 볼 수 있다.
  
// 방법 1
useEffect(() => {
      idRef.current.focus();    

    if(id.length > 9){
      pwRef.current.focus();
    }
     console.log("useEffect 실행")
  },[id])   //id가 변경될 때만 작동한다.   
  

//방법 2
// const handleIdChangeEffect = (e) => {
//    const value = e.target.value;
//    setId(value);

//   if (value.length > 9) {
//     pwRef.current.focus();
//   }
//  console.log("useEffect 실행") 
// }



//batch update 처리로 인해 값이 바로 변경되지 않는다.
//setId 이후 값이 바로 변경되지 않기 때문에 id.length가 정상작동 되지 않는(밀리는 현상)" 볼 수 있다.
//이러한 이유로 랜더링 될 경우에만 수행되는 useEffect를 사용하는 것이다.
// const handleIdChangeEffect = (e) => {
//    setId(e.target.value);
//    console.log(id);
//    if (id.length > 9) {
//     pwRef.current.focus();
//   }
// }


  
  return (
    <>
    <form>
    <div>아이디: <input type='text' ref={idRef} value={id} onChange={(e) => setId(e.target.value)} autoComplete='username'/> </div>
    {/* <div>아이디: <input type='text' ref={idRef} value={id} onChange={handleIdChangeEffect} autoComplete='username'/> </div>  */}
    <div>비밀번호: <input type='password' ref={pwRef} value={password} onChange= {(e) => setPassword(e.target.value)} autoComplete='current-password'/></div>
    </form>
    </>
  )
}

export default UseRef

useContext

: props drilling 방지 (전역 데이터를 관리)

<구성>

  • createContext : context 생성
  • Consumer : context 변화 감지
  • Provider : context 전달(to 하위 컴포넌트)

  1. FamilyContext 컴포넌트에서 context 생성
import { createContext } from "react";

//context 생성
export const FamilyContext = createContext("");

  1. GrandFather 컴포넌트에서 Provider 제공
import React from 'react'
import Father from './Father'
import { FamilyContext } from './FamilyContext';

function GrandFather() {
const houseName = "스파르타";
const pocketMoney = 10000;
  return (

     // Provider에서 제공한 value(houseName, pocketMoney)가 달라진다면 
     // useContext를 사용하고 있는 모든 컴포넌트가 리렌더링 된다.
    <FamilyContext.Provider value={{houseName,pocketMoney,}}>
    <Father/>
    </FamilyContext.Provider>
   
    
  )
}

export default GrandFather

  1. Father 컴포넌트
import React from 'react'
import Child from './Child'

function Father() {
  return (
    
    <Child></Child>
  )
}

export default Father

  1. Child 컴포넌트에서 Provider 사용
import React, { useContext } from 'react'
import { FamilyContext } from './FamilyContext';

const styles = {
  color: "red",
  fontWeight: "900",
};

function Child() {
    
  // Context를 사용하여 받아온 값
   const data = useContext(FamilyContext);
   console.log(data);

    return (
      <div>
          나는 이 집안의 막내에요.!!<br/>
          할아버지가 우리집 이름은 <span style={styles}>{data.houseName}</span>라고 하셨습니다.<br/>
          게다가 용돈도 <span style={styles}>{data.pocketMoney}</span>원만큼 주셨어요!
  
      </div>
    )
  }

export default Child

주의사항
Provider에서 제공한 value가 달라진다면 useContext를 사용하고 있는 모든 컴포넌트가 리렌더링 됩니다. 따라서 value 부분을 항상 신경써야한다.

profile
개발 중~~~ 내 자신도 발전 중😂🤣

0개의 댓글

관련 채용 정보