React - hook

lsjoon·2024년 4월 8일
1

React

목록 보기
2/6

Hook

기존의 컴포넌트에서 State와 생명주기 관리를 위해선 반드시 클래스 컴포넌트를 사용해야 했음

클래스 컴포넌트는 사용하기 다소 난해할 수 있으며, 이를 보완하면서 함수 컴포넌트에서 클래스 컴포넌트의 기능을 구현하기 위해 React 16.8 버전에서 추가됨

Hook - useState


컴포넌트 내 동적인 데이터를 관리하는 hook
state는 읽기 전용으로, 직접 수정하면 안됨 ( 직접 수정할 경우, 재렌더링이 되지 않음 )
- 따라서, state를 변경하기 위해선 setState를 사용해야 함
- setState가 실행되면, 자동으로 컴포넌트 재렌더링 실시

실시간으로 갱신되는 state 값 전달

부모 컴포넌트의 state가 갱신될 때마다, 자식 컴포넌트에서도 바뀐 state 값으로 재랜더링하도록 할 수 있음.


// App.js
import React, { useState } from 'react';
import Greeting from './components/Greeting'

function App() {
  const [ user, setUser ] = useState("")
  return (
    <div className="App">
        <input value={user} onChange={(event) => {
            setUser(event.target.value);
        }} />
        <Greeting name={user}/>
    </div>
  );
}

export default App;


// Greeting.js
import React from 'react';


function Greeting({name}) {
    return <h1>{name}님 안녕하세요.</h1>
}

export default Greeting;

state 로 Object를 가질 때

Object 멤버의 값을 변경했을 때, react는 재랜더링을 실행하지 않음.
따라서, 멤버가 변경될 경우에도 Object 자체를 갱신하도록 해야함.


import React, { useState } from 'react';

function App() {
  const [ student, setStudent ] = useState({
    name: "김민수",
    count: 0
  })
  return (
    <div className="App">
        <span>{student.name}님이 버튼을 {student.count}회 클릭하였습니다.</span><br />
        <button onClick={() => {
            setStudent((current) => {
                const newStudent = {...current}
                newStudent.count += 1
                return newStudent
            })
        }}>button</button>
    </div>
  );
}

Hook - useEffect

함수 컴포넌트에서 side effect 수행 가능

const App () => {
	useEffect(EffectCallback, Deps?)
}

EffectCallback : Deps에 지정된 변수가 변경될 때 실행할 함수
Deps : 변경을 감지할 변수들의 집합(배열)

  • EffectCallback 함수가 호출되는 경우
    - 컴포넌트가 최초로 렌더링 될 때,
    - 지정한 State나 Prop가 변결될 때,
  • Deps 를 빈 배열로 둘 경우
    - 컴포넌트 생성 시 최초에 1회 호출됨

  • useEffect 내에서 다른 함수를 return 할 경우
    - state가 변경되어 컴포넌트가 다시 렌더링 되기 전 호출
    - 컴포넌트 소멸 시 호출됨


// App.js
import React, { useState } from 'react';
import Greeting from './components/Greeting';

function App () {
  const [isCreated, setIsCreated] = useState(false);
  
  const handleCreate = () => {
  	setIsCreated((curr) => {
    	return !curr;
    });
  };
  
  return 
      <div>
        <button onClick={handleCreate}>
          클릭 !
        </button>
        {isCreated && <Greeting />}
      </div>
}
  
  
// Greeting.js
import React, { useEffect } from "react";

function Greeting() {
  useEffect(() => {
    console.log("컴포넌트가 생성되었습니다.");

    return () => {
      console.log("컴포넌트가 소멸되었습니다.");
    };
  }, []);

  return <h1>안녕하세요</h1>;
}

export default Greeting;

Hook - useMemo

변수를 메모

지정한 State나 Props가 변경될 때 해당 값을 활용해 계산된 값을 메모이제이션하여 재렌더링 시 불필요한 연산을 줄임

  • useMemo 함수 내의 연산은 렌더링 단계에서 이루어지기 때문에 시간이 오래 걸리는 로직은 작성하지 않는 것이 좋음
const App () => {
  const [firstName, setFirstName] = useState('정글')
  const [lastName, setlastName] = useState('김')
    
  // 이름과 성이 바뀔 때마다 풀네임을 메모이제이션
  const fullName = useMemo(()=> {
  	return `${firstName} ${lastName}`
  }, [firstName, lastName]);  
}

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

const App = () => {
    const [foo, setFoo] = useState(0)
    const [bar, setBar] = useState(0)

    const multi = useMemo(() => {
        let sum = foo*bar
        return sum
        }, [foo, bar])

    return (
        <div className="App">
            <input value={foo} onChange={(event)=>{setFoo(parseInt(event.target.value))}} />
            <input value={bar} onChange={(event)=>{setBar(parseInt(event.target.value))}} />
            <div>{multi}</div>
        </div>
    )
}

export default App;

Hook - useCallback

함수를 메모

함수를 메모이제이션하여, 재렌더링 시 함수가 다시 생성되는 것을 방지


const App () => {
  const [firstName, setFirstName] = useState('정글')
  const [lastName, setlastName] = useState('김')
    
  // 이름과 성이 바뀔 때마다 풀네임을 return 하는 함수를 메모이제이션
  const getFullName = useCallback(()=> {
  	return `${firstName} ${lastName}`
  }, [firstName, lastName]);  
}

return <>{getFullName()}</>

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

function App() {    
    const [ foo, setFoo ] = useState(0)
    const [ bar, setBar ] = useState(0)

    const calc = useCallback(() => {
        return foo + bar
    }, [ foo, bar ])

  return (
    <div className="App">
        <input value={foo} onChange={(event)=>{
            setFoo(parseInt(event.target.value))
        }}/>
        <input value={bar} onChange={(event)=>{
            setBar(parseInt(event.target.value))
        }}/>
        <div>{calc()}</div>
    </div>
  );
}
// 아래의 useMemo와 useCallback은 동일하게 작동함

useMemo(()=> fn, deps)

useCallback(fn, deps)

Hook - useRef

컴포넌트 생애 주기 내에서 유지할 ref 객체를 반환
- ref 객체는 .current 라는 속성을 가지며, 이 값을 자유롭게 변경 가능
- React에서, DOM Element에 접근할 때 사용
- useRef에 의해 반환된 ref 객체가 변경되어도 컴포넌트가 재렌더링되지 않음

const App = () => {
  const inputRef = useRef(null)
  const onButtonClick = () => {
  	inputRef.current.focus()
  }
  
  return (
    <div>
    	<input ref={inputRef} type="text" />
    	<button onClick={onButtonClick}>
          input으로 포커스
        </button>
    	</input>
    </div>
  )
}

import React, {useRef} from 'react';

function App() {
    const inputRef = useRef(null)

  return (
    <div className="App">
        <input ref={inputRef} />
        <button onClick={() => {alert(inputRef.current.value)}}>Click!</button>
    </div>
  );
}

export default App;

Hook - custom Hook

// app.js
import useToggle from "./hooks/useToggle";

function App() {
    const { isOn, toggle } = useToggle(false);

  return (
    <div className="App">
        <button onClick={() => toggle()>
          {isOn ? "켜짐" : "꺼짐"}
		</button>
    </div>
  );
}

export default App;

// useToggle.js
function useToggle = (initValue) => {
  const [isOn, setIsOn] = useState(initValue)
  const toggle = () => {
    setIsOn(curr => {
    	return !curr
    })
  }
  return { isOn, toggle }
}

export default useToggle;
profile
중요한 것은 꺾여도 그냥 하는 마음

0개의 댓글