본문 바로가기
react

[React]Hooks함수 정리1(useState, useRef, useEffect, useContext)

by 남민섭 2023. 1. 10.
728x90
반응형

용어 정리

● 렌더(render) : 화면에 그리다(생성)

 

 리렌더링/업데이트: 재정의/변경   (변수가 바뀔때는 리렌더링 안함!!!)

변경 하려면!!!!!!

 

1) 부모요소가 주는 props가 변경 되었을 때!!!

2) 상태가 변경 되었을 때!!!!!

 

 마운트 : 화면에 나타남

 

 언마운트: 화면에 사라짐

 

1. useState

2. useRef

3. useEffect

4. useContext

 

 

1. useState

useState 가져오기

import React,{useState} from 'react';

 

구문) 

const [number, setNumber] = useState(0)  * state생성(구조분해할당)

 

return array[상태, 상태업데이트 함수] = useState(초기값)

배열로 받음(리턴)!!!!!!

 

주의!!!!

let number = 10 이처럼 변수선언으로는 할당 불가능

 

꼭 setNumber함수!!  number를 업데이트 해주는 함수 사용해야한다.  ex)setNumber(10) 

 

실습

App.js

import './App.css';
import FuncCompoenent2 from './components/Funccomponent2';


function App() {
  return (
    //{ name: "green", children: "안녕하세요"} =>props   FuncCompoenent2에서 이렇게 전달 받는다는거
    <div className="App">
      <FuncCompoenent2 name="green" >안녕하세요</FuncCompoenent2>
      //안녕하세요는 props.children으로 전달      
    </div>
  );
}


export default App;

 

 

Funccompoenent2.js

import React, {useState} from "react";

const Funccompoenent2 = ({name, children}) => {
    const [number, setNumber] = useState(0)  //배열 구조분해할당
    const onAddnumber = () => {  //상태업데이트함수 사용했을때
        setNumber(number+1)
    } 
    return(
        <div>
            <h2>{number}<button onClick={onAddnumber}>+1</button></h2>
            {name}{children}
        </div>
    )
}

export default Funccompoenent2;

 

출력값

 

 

 


 

2.useRef

 

useRef 가져오기

import React,{useRef} from 'react';

 

구문)

const ref = useRef(vlaue) ▶▶▶ {current : value}

객체로 받음(리턴)!!!!!!

 

ex)

const refNum = useRef(0)

 

ref값 변경 /수정

구문)

ref.current = "green"  ▶▶▶ {current : value}

 

 

Ref특징1

컴퍼넌트의 전 생애주기동안 유지됨(무슨말이지???....ㄷㄷ)

컴포넌트가 리렌더링 되어도 언마운트 되기 전까지 유지됨

 

Ref가 변경 -> 렌더링x ->변수들의 값 유지

 

Ref용도

저장공간

값이 변경되어도 렌더링이 일어나지 않으며

렌더링이 되어도 초기화 되지않고 값이 유지되는 저장공간(위와 같은말)

 

실습예시1)

RefSample.js

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

const RefSample = () => {
    //state생성
    const [stateNum, setStateNum] = useState(0);
    //ref생성
    const refNum = useRef(0);  //{current : 0}
    //변수생성
    let varNum = 0;
    //변수 수정함수 구현
    const addLet = () => {
        varNum = varNum + 1;
        console.log(varNum)
    }
    //ref수정 함수 구현
    const addRef = () => {
        refNum.current = refNum.current+1
    }
    //setState호출함수구현
    const addState = ()=> {
        setStateNum(stateNum +1)
    }
    return (
        <div>
           <p>state:{stateNum} </p>
           <p>Rfe: {refNum.current}</p> 
           <p>let: {varNum}</p>
           <button onClick={addState}>State+1</button>
           <button onClick={addRef}>Ref+1</button>
           <button onClick={addLet}>let+1</button>
        </div>
    );
};

export default RefSample;

 

App.js

import React from 'react';
import RefSample from './RefSample';

const App = () => {
    return (
        <div>
           <RefSample/>
        </div>
    );
};

export default App;

 

아래 출력 영상 확인▼

 

state버튼은 useState 함수 사용하여 계속 숫자가 업데이트 되는걸 볼 수 있음

 

Ref버튼은 클릭했을때 반응없다가 state버튼을 클릭하면 Ref버튼을  클릭했을때 저장된 값을 불러오는걸 볼 수 있음

(저장된 값 유지)

 

let버튼은 콘솔창에 숫자가 계속 업데이트 되는걸 볼수 있음 하지만 state버튼 클릭 후 let버튼 클릭하면 저장된 값이 다 초기화됨 1부터 다시 업데이트됨

(저장된 값 유지안됨)

 


 

Ref특징2

DOM요소의 접근:  document.querySelector() 같은 역활을 해줌


const nameInput = useRef();
<input ref={nameInput}/>

 

실습예시2)

DomRefSample.js

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

const DomRefSample = () => {
    const [name, setName] = useState("")
    const inputRef = useRef();
    const onReset = () => {
        setName("");
        //document.querySelector('#inputname').focus(); 
        //위 구문과 밑에 구문 비교
        inputRef.current.focus();
    }
    return (
        <div>
            <input name="name" value={name} id="inputname" ref ={inputRef} 
            						//ref 
            onChange={(e)=>setName(e.target.value)}/>
            <button onClick={onReset}>초기화</button>
        </div>
    );
};

export default DomRefSample;

 

App.js

import React from 'react';
import DomRefSample from './DomRefSample';

const App = () => {
    return (
        <div>
           <DomRefSample/>
        </div>
    );
};

export default App;

 

출력값

 


 

3.useEffect

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

(이 함수를 사용하면 처음 화면이 나타날 때 특정 작업을 할 수 있음,

리렌더링 될때마다 특정 작업도 할 수 있음)

 

마운트, 언마운트, 업데이트 시 실행할 작업 설정하기

 

useEffect 구문

useEffect(콜백함수,[연관배열])

 

1) 렌더링 될때 마다 실행

useEffect(()=>{
    //실행할 코드
})

 

 

2) 화면에 첫 렌더링 될때 실행 + value값이 변경될때만 실행

useEffect(()=>{
    //실행할 코드
},[value])

 

 

3)화면에 첫 렌더링 될때만 실행

 useEffect(()=>{
    //실행할 코드
},[])



4) 마운트됐을때 실행, 언마운트됐을때 실행

useEffect(()=>{
    //마운트 됐을때 실행코드
    return()=>{
        //언마운트 됐을때 실행
        }
},[])

 

실습

EffectHookSample.js

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

const EffectHookSample = () => {
    const [number, setNumber] = useState(0)
    const [text, setText] = useState("")
    const onClick = () =>{
        setNumber(number+1)
    }
    //렌더링 될때마다 매번 실행
    useEffect(()=>{
        console.log('렌더링되었습니다')
    })
    //처음 마운트 될때만 실행
    useEffect(()=>{
        console.log("마운트되었습니다");
    },[]) 
    useEffect(()=>{
        console.log("number가 변경되었습니다");
    },[number]) //number가 업데이트 될때마다 실행
    return (
        <div>
            <span>{number}</span>
            <button onClick={onClick}>update</button>
            <input value={text} onChange={(e)=>setText(e.target.value)}/>
        </div>
    );
};

export default EffectHookSample;

 

App.js

import React from 'react';
import EffectHookSample from './EffectHookSample';

const App = () => {
    return (
        <div>
            <EffectHookSample/>
        </div>
    );
};

export default App;

 


4. ContextAPI(useContext)

 

어떤 컴포넌트 트리내에서 최상위 컴포넌트부터 최말단 컴포넌트에 걸쳐 전역으로 관리해야할 데이터를 관리 (props처럼 위에서 아래로 차례대로 하나하나 전달안해도되고 어디로든 전달 가능)

 

 

1) context 생성

context : 전역데이터를 담고있는 저장공간
createContext(초기값) 함수호출

import { createContext } from "react";
export const UserContext = createContext("green");

 

2) context 사용

Context에 저장되어 있는 전역 데이터에 접근할 수 있음. 이 방법은 함수 컴포넌트에서만 가능

const testContext = useContext(userContext)  //초기값

 

 

3) context값 지정

<testContext.Provider>
<App/>
</testContext.Provider>

 

 

 

 

실습 예시)

다크모드 전환하기

component 폴더 새로 만들어주기

 

Header.js

import React, {useContext} from "react";
import { NameContext } from "../context/NameContext";
import { DarkContext } from '../context/DarkContext';
const Header = () =>{
    const siteName = useContext(NameContext);
    const {isDark} = useContext(DarkContext);
    return(
        <div className="header" style={{
            backgroundColor: isDark ? "#222" : null,
            color: isDark ? "#fff" : "#222"
        }}>
            <h1>{siteName}</h1>
            <ul>
                <li>menu1</li>
                <li>menu2</li>
                <li>menu3</li>
            </ul>
        </div>
    )
}
export default Header;

 

Main.js

import React, { useContext } from 'react';
import { DarkContext } from '../context/DarkContext';

const Main = () => {
    const {isDark} = useContext(DarkContext)
    return (
        <div className='main'style={{
            backgroundColor: isDark ? "#222" : null,
            color: isDark ? "#fff" : "#222"
        }}>
          메인페이지입니다.  
        </div>
    );
};

export default Main;

 

Footer.js

import React, { useContext } from 'react';
import { DarkContext } from '../context/DarkContext';

const Footer = () => {
    const {isDark, setIsDark} = useContext(DarkContext);
    const darkToggle = () =>{
        setIsDark(!isDark)
    }
    return (
        //isDark가 true면 배경색을 #222로
        //글자색은 #fff색으로 변경
        <div className='footer'style={{
            backgroundColor: isDark ? "#222" : null,
            color: isDark ? "#fff" : "#222"
        }}>
            <button onClick={darkToggle}>다크모드</button>
        </div>
    );
};

export default Footer;

 


context파일 새로 만들어주기

DarkContext.js

import { createContext } from "react";

export const DarkContext = createContext(null);

 

NameContext.js

import { createContext } from "react";

export const NameContext = createContext("abc");

 


 

App.js

import {useState} from "react";
import './App.css';
import Footer from './components/Footer';
import Header from './components/Header'; // default붙음
import Main from './components/Main';
import { DarkContext } from "./context/DarkContext";
import { NameContext } from './context/NameContext'; 
//default없으면 중괄호 붙음(이름으로 내보내기)


function App() {
  const [isDark, setIsDark] = useState(false);
  return (
    <NameContext.Provider value="bbbbbb">
      {/* 위 태그로 감싸주면 안에 있는 내용을 다 사용할수 있음*/}  
      <DarkContext.Provider value ={{isDark, setIsDark}}>
                           {/* isDark: isDark, setIsDark:setIsDark 줄여씀*/} 
      <div className="App">
        <Header/>
        <Main/>
        <Footer/>
      </div>
      </DarkContext.Provider>
    </NameContext.Provider>
  );
}
export default App;

Provider로 감싸주면 그 하위에 있는 모든 컴포넌트들은 react Context에 저장되어 있는 전역 데이터에 접근 가능. value 속성값을 지정하지 않을 경우 Context 생성할 때 넘겼던 default값 사용

 

 

출력값

 

 

 

728x90
반응형

댓글