React Hooks

naisΒ·2022λ…„ 2μ›” 27일
0
post-thumbnail

πŸ‘©β€πŸ«λ¦¬μ•‘νŠΈ Hooks의 μ’…λ₯˜λ“€μ„ μ •λ¦¬ν•˜κ³  μ‹€μŠ΅ λ•Œ μ‚¬μš©ν•œ μ˜ˆλ“€μ„ λ³΅μŠ΅ν•˜κ³ μž μž‘μ„±ν•œλ‹€

useState()

  • μ»΄ν¬λ„ŒνŠΈλŠ” state λΌλŠ” μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœκ°’μ„ κ°€μ§ˆ 수 μžˆλ‹€
  • μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœλ₯Ό κ°„νŽΈν•˜κ²Œ μƒμ„±ν•˜κ³  μ—…λ°μ΄νŠΈν•  수 있게 ν•΄μ£ΌλŠ” ν•¨μˆ˜
  • setState λ₯Ό μ‚¬μš©ν•΄μ„œ state 의 값을 λ³€κ²½ν•˜κ²Œ 되면 ν™”λ©΄μ—λŠ” λΈŒλΌμš°μ €μ— λ Œλ”λ§λœλ‹€
const [state,setState] = useState(5);

Lazy initial state

  • λŒ€λΆ€λΆ„ state 의 μ΄ˆκΈ°κ°’μ„ 정적인 값듀이 λ“€μ–΄μ˜€μ§€λ§Œ ν•¨μˆ˜κ°€ λ“€μ–΄μ˜€λŠ” κ²½μš°λ„ μžˆλ‹€.
  • 단 ν•¨μˆ˜κ°€ ν•΄λ‹Ή state 의 μ΄ˆκΈ°κ°’μ„ 가지고 올 λ•Œ 무거운 μž‘μ—…μ„ ν•΄μ•Όν•œλ‹€λ©΄? 무거운 μž‘μ—…μ΄ λ˜λŠ” ν•¨μˆ˜κ°€ λ Œλ”λ§μ‹œλ§ˆλ‹€ κ³„μ†ν•΄μ„œ ν˜ΈμΆœν•˜λŠ” ν˜„μƒμ΄ λ°œμƒν•  것이닀 (μ„±λŠ₯ μ €ν•˜ )
  • μ΄ˆκΈ°μƒνƒœ λ˜ν•œ μ§€μ—°λœ ꡬ성 μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€
  • ν•¨μˆ˜κ°€ λ°˜ν™˜ν•˜λŠ” κ°’μœΌλ‘œ ν™œμš©ν•  수 μžˆλ‹€
  • μ•½κ°„ 비동기 ν•¨μˆ˜μ²˜λŸΌ μ²˜λ¦¬λ˜λŠ” 것이닀 초기 값을 μƒμ„±ν•˜λŠ” ν•¨μˆ˜λ₯Ό κΈ°λ‹€λ Έλ‹€κ°€ μ²˜λ¦¬ν•˜μ§€λ§κ³  초기 λ Œλ”λ§ μ‹œμ—λ§Œ 이 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λΌλŠ” 의미!!
const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

useEffect()

  • ν•¨μˆ˜ μ»΄ν¬λ„ŒνŠΈμ—μ„œ λ°œμƒ κ°€λŠ₯ν•œ λΆ€μˆ˜νš¨κ³Ό(side Effetcts) λŠ” React.useEffect ν›…μœΌλ‘œ 관리
  • λ Œλ”λ§ 될 λ•Œ λ§ˆλ‹€ 맀번 μ‹€ν–‰λœλ‹€(μ •ν™•νžˆ λ Œλ”λ§ 된 직후에 μ‹€ν–‰λœλ‹€)
  • 인자둜 μ½œλ°±ν•¨μˆ˜λ₯Ό λ°›λŠ”λ‹€
  • ν˜•νƒœλ‘œλŠ” 두가지가 μžˆλ‹€
useEffect(()=>{

	//  μž‘μ—… 
}); // 인자둜 ν•˜λ‚˜μ˜ 콜백만 λ°›μŒ, λ Œλ”λ§ 될 λ•Œ λ§ˆλ‹€ μ‹€ν–‰

useEffect(()=>{
	//μž‘μ—…

},[value]) //  μ½œλ°±ν•¨μˆ˜μ™€ λ°°μ—΄(λ””νŽœλ˜μ‹œ μ–΄λ ˆμ΄), 
// 화면에 첫 λ Œλ”λ§ λ λ•Œ μ‹€ν–‰
// value 값이 λ°”λ€” λ•Œ μ‹€ν–‰ 
// [] (empty λ°°μ—΄λ‘œ λ„£μ–΄μ£Όλ©΄ ν™”λ©΄ λ Œλ”λ§ μ‹œμ—λ§Œ μ‹€ν–‰!) 

clean up - 정리

  • μ»΄ν¬λ„ŒνŠΈκ°€ UIμ—μ„œ 제거될 λ•Œ (unmount)될 λ•Œ μ •λ¦¬λ˜μ–΄μ•Ό ν•˜λŠ” λΆ€λΆ„ μ²˜λ¦¬ν•œλ‹€

  • μ΄λŠ” λ©”λͺ¨λ¦¬ λˆ„μˆ˜(Memory Leak) 방지λ₯Ό μœ„ν•΄ UI μ—μ„œ μ»΄ν¬λ„ŒνŠΈλ₯Ό μ œκ±°ν•˜κΈ° 직전에 μˆ˜ν–‰

  • λ‹€μŒ μ΄νŽ™νŠΈ ν•¨μˆ˜κ°€ 싀행될 λ•Œ λ§ˆλ‹€ 클린업 ν•¨μˆ˜κ°€ λ¨Όμ € μ‹€ν–‰λ˜μ–΄ 정리 ν•œλ‹€

  • return ν•¨μˆ˜ μ•ˆμ—μ„œ μš°λ¦¬κ°€ μ›ν•˜λŠ” μž‘μ—…μ„ ν•΄μ£Όλ©΄λœλ‹€

  • ν•¨μˆ˜λ₯Ό 리턴해주면 ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈκ°€ μ–Έλ§ˆμš΄νŠΈλ  λ•Œ, λ‹€μŒ λ Œλ”λ§ μ‹œ 뢈릴 useEffect κ°€ μ‹€ν–‰λ˜κΈ° 전에 이 ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ” 것이닀

useEffect(()=>{
//ꡬ독

return() =>{
// ꡬ독 해지 
} /* return의 μ€‘κ΄„ν˜Έλ₯Ό ν•΄μ§€ν•˜μ§€ μ•Šκ³  μ“°λŠ” 것이 ꢌμž₯, 

clean ν•  λ‚΄μš©μ„ 이 뢀뢄에 μž‘μ„±ν•˜λ©΄λ¨*/
},[]); 

setInterval 을 μ΄μš©ν•œ μ‹€μŠ΅ 진행

  • setInterval 이 3μ΄ˆλ§ˆλ‹€ μ§€μ†μ μœΌλ‘œ μ—…λ°μ΄νŠΈλ₯Ό ν•˜λŠ”λ° 이 λ•Œ ν™”λ©΄μ—μ„œ μ•ˆλ³΄μ΄κ²Œ λ λ•Œ 이 타이머λ₯Ό λ©ˆμΆ°μ•Όν•˜κΈ° λ•Œλ¬Έμ— clean - up 을 μ§„ν–‰ν•˜μ—¬μ„œ clearInterval 해주어야지 λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”κ²ƒμ„ ν™•μΈν–ˆλ‹€
export default function App() {
  //  μ»΄ν¬λ„ŒνŠΈ μƒνƒœ
  // [state,setState] = useState(???);
  // 1.tuple data type = [state,setState]
  //2. initial = static | Lazy
  // const [appName, setAppName] = useState(props.appName);

  React.useEffect(() => {
    console.log(`change app name:${appName}`);

     //μ‚¬μ΄λ“œ μ΄νŽ™νŠΈ μ„€μ •
     // νƒ€μž„ 컨트둀 (React 에 μ˜ν•΄ κ΄€λ¦¬λ˜λŠ” 것이 μ•„λ‹˜: λΆ€μˆ˜νš¨κ³Ό )
     // 3초 λ§ˆλ‹€ μ§€μ†μ μœΌλ‘œ μ—…λ°μ΄νŠΈλ₯Ό μ‹€ν–‰ν•˜λ €κ³  함
     const clearId = setInterval(() => setAppName((prevState) => prevState + `🀣`), 3000);

     return (
       () => {
         clearInterval(clearId);
       },
       [appName]
     );
 / }); // ꡬ독 보닀 μ·¨μ†Œλ₯Ό λ¨Όμ €ν•œλ‹€ ,

useRef()

const ref = useRef(value)

{current : value} /// μƒμ„±ν•˜λ©΄ 객체가 μƒμ„±λ˜λŠ” 것이닀 
  • λ³€ν™”λŠ” κ°μ§€ν•˜μ§€λ§Œ κ·Έ λ³€ν™”κ°€ λ Œλ”λ§μ„ λ°œμƒμ‹œν‚€λ©΄ μ•ˆλ˜λŠ” 값을 λ‹€λ£° λ•Œ νŽΈλ¦¬ν•˜λ‹€
  • ref object 둜 μš°λ¦¬κ°€ μ„ΈνŒ…ν•΄μ€€ value λŠ” current 에 μ €μž₯이 λœλ‹€
  • μˆ˜μ •μ΄ κ°€λŠ₯ν•˜κΈ° 떄문에 μš°λ¦¬κ°€ μ›ν•˜λŠ” κ°’μœΌλ‘œ μ €μž₯ κ°€λŠ₯
  • λ°˜ν™˜λœ ref λŠ” μ»΄ν¬λ„ŒνŠΈμ˜ μ „ 세계 μ£ΌκΈ°λ₯Ό 톡해 μœ μ§€λœλ‹€( μ»΄ν¬λ„ŒνŠΈκ°€ 계속 λ Œλ”λ§ λ˜μ–΄λ„ umout 되기 μ „κΉŒμ§€λŠ” 값을 κ·ΈλŒ€λ‘œ μœ μ§€ν•  수 μžˆλ‹€λŠ” 것이닀)
  • μ—­ν• 
    • μ €μž₯곡간
      - state 와 λΉ„μŠ·ν•œ μ—­ν• λ‘œ μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœλ₯Ό μ €μž₯ν•˜λŠ”λ° state λŠ” 변화될 λ•Œ λ§ˆλ‹€ λ Œλ”λ§μ΄ 이루어지고 μ»΄ν¬λ„ŒνŠΈμ˜ λ‚΄λΆ€ λ³€μˆ˜λ“€μ΄ μ΄ˆκΈ°ν™”λœλ‹€
      - μ΄λŸ¬ν•œ 단점이 Ref μ•ˆμ— 값을 μ €μž₯ν•΄μ£Όκ³  이 값을 아무리 변경해도 λ Œλ”λ§μ΄ 이루어지지 μ•ŠλŠ”λ‹€ β†’ λ³€μˆ˜λ“€μ˜ 값이 μœ μ§€λœλ‹€ !!
      - λΆˆν•„μš”ν•œ λ Œλ”λ§μ„ μœ μ§€ν•  수 μžˆλŠ” 것
      - λ³€κ²½ μ‹œ λ Œλ”λ§μ΄ 이루어지지 μ•Šμ•„μ•Ό ν•˜λŠ” 값듀을 μœ μ§€ν•˜κΈ° μœ„ν•΄μ„œ μœ μš©ν•˜λ‹€

      /* eslint-disable indent */
      import { useState, useRef } from 'react';
      import logo from './logo.svg';
      
      import './App.css';
      
      function App() {
      
        const [count, setCount] = useState(0);
        const countRef = useRef(0);
      
        const increaeRef = () => {
          countRef.current += 1;
        };
      
        return (
          <div>
            <p>You clicked ref {countRef.current} times</p>
            <p>You clicked state {count} times</p>
            <button onClick={() => setCount(count + 1)}>state Click me</button>
            <button onClick={increaeRef}>ref Click me</button>
          </div>
        );
      }
      
      export default App;

      πŸ“Œ ref click me λ²„νŠΌμ€ 클릭해도 ν™”λ©΄μ˜ λ³€ν™”λŠ” 계속 0 이닀가 state λ₯Ό λ³€κ²½ν•˜μ—¬ λ Œλ”λ§λ˜λ©΄ κ·Έμ œμ„œμ•Ό 카운트 λ˜μ—ˆλ˜ 만큼 화면에 κΈ°λ‘λ˜λŠ” 것을 ν™•μΈν–ˆλ‹€

    • Dom μš”μ†Œμ— μ ‘κ·Ό

      • Dom μš”μ†Œμ— μ ‘κ·Όν•΄μ„œ μ—¬λŸ¬κ°€μ§€ 일듀을 ν•  수 μžˆλ‹€
      • document.quertselector κ³Ό 같은 μ—­ν• 
/* eslint-disable indent */
import { useState, useRef, useEffect } from 'react';
import logo from './logo.svg';

import './App.css';

// const Div = (props) => <div {...props} />;

function App() {

  const [name, setname] = useState('홍길동');
  const countRef = useRef();

  useEffect(() => {
    countRef.current.focus();
  });

  const increaeRef = () => {
    countRef.current += 1;
  };

  return (
    <div>
      <input type="text" ref={countRef}></input>
      <p>{name}</p> // 
      <button onClick={() => setname(countRef.current.value)}>state Click me</button>
		</div>
  );
}

export default App;

πŸ“Œ useEffect 을 μ‚¬μš©ν•˜μ—¬ λ Œλ”λ§ 직후에 input νƒœκ·Έμ— focus κ°€ 가도둝 ref λ₯Ό 톡해 μ„€μ •

πŸ“Œ ref 둜 인해 input 의 value 값을 κ°€μ Έμ™€μ„œ 이벀트 ν΄λ¦­μ‹œ state κ°’ 변경도 κ°€λŠ₯

  • 일반 λ³€μˆ˜μ™€ Ref 의 차이점
    • 일반 λ³€μˆ˜μ™€ ref λ‘˜ λ‹€ λ Œλ”λ§μ΄ 이루어지지 μ•Šμ•„μ„œ 값이 λ³€κ²½λ˜λ„ 화면에 μ•ˆλ³΄μΈλ‹€
    • μ»΄ν¬λ„ŒνŠΈλ₯Ό λ‚˜νƒ€λ‚΄λŠ” ν•¨μˆ˜κ°€ λ‹€μ‹œ λΆˆλ¦¬λŠ” 것 (ν•¨μˆ˜κ°€ 뢈릴 λ•Œ λ§ˆλ‹€ λ³€μˆ˜λ“€μ€ μ΄ˆκΈ°ν™”λœλ‹€ 그런데 ref λŠ” μ»΄ν¬λ„ŒνŠΈκ°€ 마운트되고 마운트 ν•΄μ§€λ˜κΈ° μ „κΉŒμ§€ κ·Έ 값을 μœ μ§€ν•˜κΈ° λ•Œλ¬Έμ— 값이 μœ μ§€λ˜λŠ” 것이닀)

usememo()

  • μ»΄ν¬λ„ŒνŠΈλ₯Ό(κ°’) 을 κΈ°μ–΅ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
  • λ³€λ™λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ κ·Έ 전에 가지고 있던 값을 κ·Έλƒ₯ μ‚¬μš©ν•œλ‹€
  • memo β†’ memoization을 λœ»ν•œλ‹€ (λ™μΌν•œ 값을 λ¦¬ν„΄ν•˜λŠ” 값을 λ©”λͺ¨λ¦¬μ— μ €μž₯ν•΄μ„œ 또 λ‹€μ‹œ κ³„μ‚°ν•˜μ§€ μ•Šκ³  λ©”λͺ¨λ¦¬μ—μ„œ κΊΌλ‚΄μ„œ λ‹€μ‹œ μ‚¬μš©ν•˜λŠ” 것이닀)
  • ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλŠ” λ Œλ”λ§ μ‹œμ— 호좜되고 λͺ¨λ“  λ‚΄λΆ€ λ³€μˆ˜λŠ” μ΄ˆκΈ°ν™”λœλ‹€
  • 이λ₯Ό λ©”λͺ¨μ΄μ œμ΄μ…˜μ„ μ‚¬μš©ν•΄μ„œ λ©”λͺ¨λ¦¬μ— μ €μž₯ν•΄μ€€λ‹€λ©΄ 무거운 λ Œλ”λ§λ“€μ΄ 재차 μΌμ–΄λ‚˜μ§€ μ•Šκ³  λ³€μˆ˜κ°€ μ΄ˆκΈ°ν™” λ˜μ–΄λ„ λ©”λͺ¨λ¦¬μ—μ„œ λŒμ–΄λ‹€κ°€ μ‚¬μš©μ΄ κ°€λŠ₯ν•œ 것이닀
const value = useMemo(()=>{
return calculate();
},[item])
  • 첫번 μ§Έ 인자 μ½œλ°±ν•¨μˆ˜λ‘œλŠ” μš°λ¦¬κ°€ λ©”λͺ¨μ΄μ œμ΄μ…˜ 해쀄 값을 κ³„μ‚°ν•΄μ„œ return ν•œλ‹€
  • λ‘λ²ˆμ§Έ λ°°μ—΄ μ˜μ‘΄μ„± λ°°μ—΄ : ν•΄λ‹Ή μš”μ†Œμ˜ 값이 μ—…λ°μ΄νŠΈ 될 λ–„λ§Œ λ©”λͺ¨μ΄μ œμ΄μ…˜ 해쀄 값을 μ—…λ°μ΄νŠΈν•΄μ„œ λ‹€μ‹œ λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•΄μ€€λ‹€ 이도 [] 배열이면 ν•œλ²ˆλ§Œ λ™μž‘ν•œλ‹€
  • λ¬΄λΆ„λ³„ν•˜κ²Œ μ‚¬μš©ν•˜λ©΄ λΆˆν•„μš”ν•œ κ°’λ“€κΉŒμ§€ λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•˜λ©΄ 였히렀 λ”μš± λ©”λͺ¨λ¦¬ λ‚­λΉ„κ°€ 발 생 ν•  수 μžˆλ‹€
  • μ΄λŠ” 값을 κΈ°μ–΅ν•  λ•Œ κ°€μž₯ μœ μš©ν•˜κ²Œ μ‚¬μš©μ΄ 되고 그쀑 object νƒ€μž…μ„ μ‚¬μš©ν•  λ•Œ νš¨κ³Όμ μ΄λ‹€
/* eslint-disable indent */
import { useState, useMemo, useEffect } from 'react';
import logo from './logo.svg';

import './App.css';

// const Div = (props) => <div {...props} />;

function App() {

  const [num, setnum] = useState(0);
  const [check, setCheck] = useState(false);

  const todo = {
    checked: check ? 'μ™„λ£Œ' : 'λΉ„μ™„λ£Œ',
    title: ' react λ³΅μŠ΅ν•˜κΈ°',
    content: 'hook 배운거 notion 에 μ •λ¦¬ν•˜κΈ°',
  };

  useEffect(() => {
    console.log('useEffect호좜');
  }, [todo]);

  return (
    <div>
      <input
        type="checkbox"
        checked={check}
        onClick={() => {
          setCheck(!check);
        }}
      ></input>
      <p>μˆ˜ν–‰ μ—¬λΆ€ {todo.checked}</p>
      <p>title:{todo.title}</p>
      <p>content:{todo.content}</p>
      <hr />
      <input
        type="number"
        value={num}
        onChange={(e) => {
          setnum(e.target.value);
        }}
      />
    </div>
  );
}

export default App;

πŸ“Œ 이와같은 상황은 useeffect 둜 todo 만 κ±Έμ–΄λ†¨μŒμ—λ„ number input 을 변경해도 λ Œλ”λ§μ΄ 계속 λ°œμƒν•œλ‹€

πŸ€·β€β™€οΈ?? μ™œ??

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ object λŠ” μ›μ‹œκ°’μ΄ μ•„λ‹ˆλΌ 객체가 μžˆλŠ” λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό 가지고 μžˆλŠ”λ‹€
  • ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλŠ” λ Œλ”λ§μ‹œ λ‹€μ‹œ λ³€μˆ˜ 값을 ν•­λ‹Ή β†’ λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό 계속 μƒˆλ‘œ ν• λ‹Ή λ°›κ³  이전 μ£Όμ†Œμ™€ λ³€κ²½λ˜μ—ˆκΈ° λ•Œλ¬Έμ— μƒνƒœκ°’μ΄ λ³€κ²½λ˜μ—ˆλ‹€κ³  μΈμ‹ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€

μ΄λŸ¬ν•œ μƒν™©μ—μ„œ usememo κ°€ 맀우 빛을 보닀 !!

/* eslint-disable indent */
import { useState, useMemo, useEffect } from 'react';
import logo from './logo.svg';

import './App.css';

// const Div = (props) => <div {...props} />;

function App() {

  const [num, setnum] = useState(0);
  const [check, setCheck] = useState(false);

  // const todo = {
  //   checked: check ? 'μ™„λ£Œ' : 'λΉ„μ™„λ£Œ',
  //   title: ' react λ³΅μŠ΅ν•˜κΈ°',
  //   content: 'hook 배운거 notion 에 μ •λ¦¬ν•˜κΈ°',
  // };

  const todo = useMemo(
    () => ({
      checked: check ? 'μ™„λ£Œ' : 'λΉ„μ™„λ£Œ',
      title: ' react λ³΅μŠ΅ν•˜κΈ°',
      content: 'hook 배운거 notion 에 μ •λ¦¬ν•˜κΈ°',
    }),
    [check]
  );

  useEffect(() => {
    console.log('useEffect호좜');
  }, [todo]);

  return (
    <div>
      <input
        type="checkbox"
        checked={check}
        onClick={() => {
          setCheck(!check);
        }}
      ></input>
      <p>μˆ˜ν–‰ μ—¬λΆ€ {todo.checked}</p>
      <p>title:{todo.title}</p>
      <p>content:{todo.content}</p>
      <hr />
      <input
        type="number"
        value={num}
        onChange={(e) => {
          setnum(e.target.value);
        }}
      />
    </div>
  );
}

export default App;

πŸ“Œμ΄λ ‡κ²Œν•˜λ©΄ number input 을 λ³€κ²½ν•  λ•ŒλŠ” check 값이 λ³€κ²½λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ μ΄μ „μ˜ 값을 κ·ΈλŒ€λ‘œ κ°€μ Έμ˜€λŠ” 것을 ν™•μΈν–ˆλ‹€!!

useCallback()

  • μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœλ₯Ό λ³€κ²½ν•  수 μžˆλŠ” λ©”μ„œλ“œ(μ΄λ²€νŠΈμ— μ˜ν•΄ μ œμ–΄ν•  λ•Œ) 이벀트 ν•Έλ“€λŸ¬ props 전달
  • useMemo 와 λΉ„μŠ·ν•˜μ§€λ§Œ 인자둜 받은 μ½œλ°±ν•¨μˆ˜ κ·Έ 자체λ₯Ό μ €μž₯ν•΄μ£ΌλŠ” 것이닀
  • ν•¨μˆ˜κ°€ ν•„μš”ν•  λ•Œ λ§ˆλ‹€ λ‹€μ‹œ λ§Œλ“œλŠ”κ²Œ μ•„λ‹ˆλΌ λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•΄μ„œ μ“°λŠ” 것이닀
  • μ»΄ν¬λ„ŒνŠΈκ°€ 맨 μ²˜μŒμ— λ Œλ”λ§ 될 λ•Œλ§Œ 객체λ₯Ό λ§Œλ“€μ–΄μ„œ μ΄ˆκΈ°ν™”ν•΄μ£Όκ³  κ·Έ μ΄ν›„μ—λŠ” 가지고 μžˆμœΌλ©΄μ„œ μž¬μ‚¬μš©μ„ ν•  수 μžˆλŠ” 것이닀
  • 쒅속성 배열에 μ§€μ •λœ λŒ€μƒμ΄ λ³€κ²½λœλ‹€λ©΄ λ‹€μ‹œ calculate λ₯Ό λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•˜λŠ” 것이닀
const calculate = useCallback((num)=>{
	return num+1;
},[item])
  • useCallback() 이 ν•„μš”ν•œ μ˜ˆμ‹œ

    App.jsx

/* eslint-disable indent */
import { useState, useMemo, useEffect } from 'react';
import { Box } from './stateless/Box';
import logo from './logo.svg';

import './App.css';

// const Div = (props) => <div {...props} />;

function App() {
  const [size, setSize] = useState(100);
  const [theme, setTheme] = useState(true);

  const createBoxStyle = () => {
    return <{
      backgroundColor: 'red',
      width: `${size}px`,
      height: `${size}px`,
    };
  };

  useEffect(() => {
    console.log('useEffect호좜');
  }, []);

  return (
    <div style={{ background: theme ? 'white' : 'black' }}>
      <input
        type="number"
        value={size}
        onChange={(e) => {
          setSize(e.target.value);
        }}
      />
      <Box createStyle={createBoxStyle}></Box>
      <button
        onClick={() => {
          setTheme(!theme);
        }}
      >
        ν…Œλ§ˆλ₯Ό λ°”κΎΈλŠ” λ²„νŠΌ
      </button>
    </div>
  );
}

export default App;

Box.jsx

import { useState, useEffect } from 'react';

export function Box({ createStyle }) {
  const [style, setStyle] = useState({});

  useEffect(() => {
    console.log('λ°•μŠ€λ₯Ό ν‚€μš°κΈ° μœ„ν•œ μŠ€νƒ€μΌ μ‹œμž‘');
    setStyle(createStyle);
  }, [createStyle]);

  return <div style={style}></div>;
}

πŸ“Œ ν…Œλ§ˆλ₯Ό λ°”κΎΈλŠ” λ²„νŠΌμ„ λˆ„λ₯Ό μ‹œμ— 도 계속 ν•¨μˆ˜κ°€ 생성이 되고 , μƒˆλ‘œμš΄ λ©”λͺ¨λ¦¬ μ£Όμ†Œκ°€ ν• λ‹Ήλ˜λ©΄μ„œ 값이 λ°”λ€Œκ³  μžˆλ‹€

β†’ 이처럼 λ°•μŠ€μ˜ μ‚¬μ΄μ¦ˆκ°€ λ³€κ²½λ˜μ§€ μ•ŠμŒμ—λ„ 지속적 λ Œλ”λ§μ΄ ν•¨κ»˜ μ΄λ£¨μ–΄μ§€λŠ” 것은 λΆˆν•„μš”ν•œ κΈ°λŠ₯이기에 이λ₯Ό useCallback 으둜 λ§‰μ•„μ£Όμž !!

λ³€κ²½ ν›„

.App.jsx

/* eslint-disable indent */
import { useState, useMemo, useEffect, useCallback } from 'react';
import { Box } from './stateless/Box';
import logo from './logo.svg';

import './App.css';

// const Div = (props) => <div {...props} />;

function App() {
  const [size, setSize] = useState(100);
  const [theme, setTheme] = useState(true);

  const createBoxStyle = useCallback(() => {
    return {
      backgroundColor: 'red',
      width: `${size}px`,
      height: `${size}px`,
    };
  }, [size]);

  useEffect(() => {
    console.log('useEffect호좜');
  }, []);

  return (
    <div style={{ background: theme ? 'white' : 'black' }}>
      <input
        type="number"
        value={size}
        onChange={(e) => {
          setSize(e.target.value);
        }}
      />
      <Box createStyle={createBoxStyle}></Box>
      <button
        onClick={() => {
          setTheme(!theme);
        }}
      >
        ν…Œλ§ˆλ₯Ό λ°”κΎΈλŠ” λ²„νŠΌ
      </button>
    </div>
  );
}

export default App;

πŸ“Œ ν…Œλ§ˆλ₯Ό λ°”κΎΈλŠ” λ²„νŠΌμ„ μ—¬λŸ¬λ²ˆ λ™μž‘ν•˜μ—¬λ„ Box.jsx 의 useEffect 에 μ„€μ •ν•΄ 놓은 β€˜λ°•μŠ€λ₯Ό ν‚€μš°κΈ° μœ„ν•œ μŠ€νƒ€μΌ μ‹œμž‘β€™ μ΄λΌλŠ” λ©˜νŠΈκ°€ λ³΄μ΄μ§€μ•ŠλŠ”λ‹€

μ΄λŸ°μ‹μ˜ λΆˆν”Όμš”ν•œ λ Œλ”λ§μ„ μ€„μ—¬λ³΄μž~

useContext()

  • Context API μ•± μ•ˆμ—μ„œ μ „μ—­μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” 데이터듀을 μ—¬λŸ¬ μ»΄ν¬λ„ŒνŠΈλ“€ 끼리 μ‰½κ²Œ κ³΅μœ ν•  수 μžˆλ„λ‘ ν•΄μ€€λ‹€ (이 데이터 μ“°κ³  싢은 μ‚¬λžŒ~ 이라고 APP 이 λ§ν•˜λ©΄ μ“°κ³  싢은 ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈ 듀은 useContext λ₯Ό μ¨μ„œ λ°›μ•„μ˜€κΈ°λ§Œ ν•˜λ©΄λœλ‹€ !)
  • HOC 을 μ‚¬μš©ν•˜μ§€ μ•Šκ³ λ„ Context 의 value λ₯Ό 곡급 받을 수 μžˆμ–΄μ„œ 편리 μ»΄ν¬λ„ŒνŠΈμ˜ ν˜„μž¬ μ»¨ν…μŠ€νŠΈ 쀑, κ°€μž₯ κ°€κΉŒμš΄ κ³΅κΈ‰μžμ˜ value λ₯Ό 전달 λ°›κ²Œ λœλ‹€
    • κΈ°μ‘΄μ—λŠ” Context.Consumer + Render Props νŒ¨ν„΄ or κ³ μ°¨μ»΄ν¬λ„ŒνŠΈ(HOC) νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μ—¬ 문제 ν•΄κ²°

      const cartContext = useContext(CarContext);
  • useContext() 훅을 ν˜ΈμΆœν•œ μ»΄ν¬λ„ŒνŠΈλŠ” context 값이 λ³€κ²½λ˜λ©΄ λ‹€μ‹œ λ Œλ”λ§λœλ‹€
  • useContext() 훅을 μ‚¬μš©ν•˜λ €λ©΄ Context.Provider κ°€ ν•„μš”
  • λ¦¬μ•‘νŠΈλ‘œ λ§Œλ“  앱은 μ—¬λŸ¬κ°œμ˜ μ»΄ν¬λ„ŒνŠΈλ‘œ λ§Œλ“€μ–΄μ Έ μžˆλ‹€. (λŒ€λž΅ 이런 λͺ¨μ–‘μ˜ ν˜•νƒœ)

  • μ΅œμƒμœ„ μ•±μ—μ„œ 트리 ν˜•νƒœλ‘œ (μœ„μ—μ„œ μ•„λž˜λ‘œ prop λ₯Ό ν†΅ν•΄μ„œ 데이터가 μ „λ‹¬λœλ‹€)

  • λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈκ°€ μžμ‹ μ»΄ν¬λ„ŒνŠΈ νƒœκ·Έμ— 일일히 prop νƒœκ·Έλ₯Ό λ„£μ–΄μ„œ μ „λ‹¬ν•˜λŠ” ν˜•νƒœ

  • μ „μ—­μ μœΌλ‘œ μ“°λŠ” 데이터듀 ex ) user, theme , Language λ“±

  • 이런 전역적인 λ°μ΄ν„°λ“€κΉŒμ§€λ„ 일일히 μ „λ‹¬ν•œλ‹€λ©΄ 반볡적인 λ Œλ”λ§μ΄ 타고타고...쀑첩은 ν˜•νƒœκ°€ λ°œμƒν•  것 (단계 λ³„λ‘œ μ „λ‹¬ν•œλ‹€λ©΄ κ³ ν†΅μŠ€λŸ¬μ›€, 뭐 ν•˜λ‚˜ λ°”λ€Œλ©΄ μ»΄ν¬λ„ŒνŠΈ μ°Ύμ•„ λ‹€λ‹ˆλ©°μ„œ λ°”κΏ”μ•Όν•œλ‹€)

  • 이런 ν˜•νƒœλ₯Ό prop Drilling 이라고 ν•œλ‹€

    • prop Drilling
      • μ΅œμƒμœ„ μ•± μ»΄ν¬λ„ŒνŠΈκ°€ 졜 ν•˜μœ„(κ°€μž₯ ν•˜λ‹¨μ˜ μžμ‹λ“€μ—κ²Œ ) 데이터λ₯Ό μ „λ‹¬ν•˜λŠ” 과정을 λ§ν•œλ‹€
      • μ „λ‹¬ν•˜λŠ”κ³Όμ •μ—μ„œ λͺ¨λ“  쀑간 μ»΄ν¬λ„ŒνŠΈλ“€μ„ 거쳐가고 β†’ μ»΄ν¬λ„ŒνŠΈ 듀이 λ°›λŠ” props 도 λ§Žμ•„μ§€κ³  전달 과정에 μ‹€μˆ˜ν•œλ‹€λ©΄ 해결이 μ–΄λ €μ›Œμ§„λ‹€
πŸ’‘ κ·Έλ ‡λ‹€λ©΄ prop λŠ” μ‚¬μš©ν•  ν•„μš”κ°€ μ—†λŠ”κ±ΈκΉŒ?

β†’ 놉 그렇지 μ•ŠμŒ context λ§Œμ„ μ‚¬μš©ν•œλ‹€λ©΄ μ•„λž˜μ™€ 같은 문제점 λ°œμƒ

1 ) Context λ₯Ό μ‚¬μš©ν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈλ₯Ό μž¬μ‚¬μš©ν•˜κΈ° μ–΄λ €μ›Œμ§ˆ 수 μžˆλ‹€

2 ) Prop drilling 을 ν”Όν•˜κΈ° μœ„ν•œ λͺ©μ μ΄λΌλ©΄ Component Composition (μ»΄ν¬λ„ŒνŠΈ ν•©μ„±) 을 λ¨Όμ € κ³ λ € ν•΄λ³΄μž

πŸ’‘ context 의 vlaue 변경이 μž¦λ‹€λ©΄?

β†’ 자주 λ³€κ²½λ˜μ§€ μ•Šμ€ μ»¨ν…μŠ€νŠΈλ₯Ό λΆ„λ¦¬ν•΄μ„œ 별도 κ΄€λ¦¬ν•˜κΈ° , μ»΄ν¬λ„ŒνŠΈλ₯Ό λ‚˜λˆˆ ν›„ 자주 λ³€κ²½λ˜μ§€ μ•ŠλŠ” μ»΄ν¬λ„ŒνŠΈλŠ” useMemo λ₯Ό μ‚¬μš©ν•˜μ—¬ propsκ°€ λ³€κ²½λ˜μ§€ μ•Šμ„ 경우 λ‹€μ‹œ λ Œλ”λ§ ν•˜μ§€ μ•Šλ„λ‘ μƒμ„±ν•˜λŠ”κ²ƒμ΄ μ„±λŠ₯ 이슈λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€

customhook()

  • hook 을 ν™œμš©ν•˜μ—¬ μ‚¬μš©μžκ°€ μ›ν•˜λŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λ„λ‘ λ§Œλ“  ν•¨μˆ˜λ₯Ό 의미
  • μ»΄ν¬λ„ŒνŠΈ λ‘œμ§μ„ μž¬μ‚¬μš© κ°€λŠ₯ν•œ ν•¨μˆ˜λ‘œ μΆ”μΆœ ν•  수 μžˆλ‹€
  • custom hook의 이름은 λ°˜λ“œμ‹œ use 둜 μ‹œμž‘ν•΄μ•Όν•œλ‹€
    • ν•œλˆˆμ— 보아도 Hook κ·œμΉ™ μ μš©λ˜λŠ”μ§€ νŒŒμ•…
    • use둜 μ‹œμž‘ν•˜λ©΄ Hook κ·œμΉ™ μœ„λ°˜ μ—¬λΆ€λ₯Ό react κ°€ μžλ™ 체크
    • μ΅œμƒμœ„(at the Top level) μ—μ„œλ§Œ Hook을 호좜
    • 였직 React ν•¨μˆ˜ λ‚΄μ—μ„œ Hook을 호좜
// ν…Œλ§ˆ μ»¨ν…μŠ€νŠΈ μƒμ„±ν•˜κΈ° (ν…Œλ§ˆ :  읽기 μ „μš© )
// ν…Œλ§ˆ μ»¨ν…μŠ€νŠΈ 값을 생성 κ³Όμ •μ—μ„œ κ³΅κΈ‰ν•˜κΈ°
// ν…Œλ§ˆ μ»¨ν…μŠ€νŠΈ 값을 λ°˜ν™˜ν•˜λŠ” μ»€μŠ€ν…€ ν›… λ§Œλ“€μ–΄ 내보내기

// ν…Œλ§ˆ 값은 λŸ°νƒ€μž„(μ‹€ν–‰) 쀑에 λ³€κ²½λ˜μ§€ μ•ŠλŠ” κ°’μ΄λ―€λ‘œ κ·Έ 값을 κΈ°μ–΅ν•΄λ‘λŠ” 것이 μ’‹λ‹€ .

import * as React from 'react';

const defaultTheme = {
  light: {
    background: '#f3f3f3',
    color: '#191919',
    accent: '#0d71f4',
  },
  dark: {
    background: '#131313',
    color: '#f9f9f9',
    accent: '#f40d66',
  },
};

const ThemeContext = React.createContext(defaultTheme);

// μ»΄ν¬λ„ŒνŠΈ μ»¨ν…μŠ€νŠΈ 값을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό 생성
export const useTheme = () => {
  const theme = React.useContext(ThemeContext);

  if (!theme) {
    throw new Error('ThemeContext  μ•ˆμ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹ˆκΉŒ 확인해 ');
  }

  return React.useMemo(() => theme, [theme]);
};

useReducer()

  • useState 의 λŒ€μ²΄ ν•¨μˆ˜ (λ³΅μž‘ν•œ μƒνƒœ 관리가 μ–΄λ ΅λ‹€)
  • μ—¬λŸ¬κ°œμ˜ μƒνƒœλ₯Ό κ΄€λ¦¬ν•΄μ£ΌλŠ” 역할이라고 보면 λœλ‹€ .

const [state, dispatch] = useReducer(reducer,initialState,initialZation)

initialState

  • λ¦¬λ“€μ„œ ν•¨μˆ˜κ°€ κ΄€λ¦¬ν•˜λŠ” μƒνƒœλ‘œ μ‚¬μš©μžμ— μ˜ν•΄ μ΄ˆκΈ°κ°’μ„ 전달 받을 수 있음
const initialSinario = [
  { id: 'lkfs-fjkld-jflkxf', content: 'λ§ˆλΈ” 캐릭터 좩돌' },
  { id: 'kdfd-wkdif-kclskw', content: 'DC 캐릭터 λŒ„μŠ€ νŒŒν‹°' },
];

reducer

  • (state , action) 을 λ°›μ•„μ„œ μƒˆλ‘œμš΄ newState λ₯Ό λ°˜ν™˜
  • λ””μŠ€νŒ¨μΉ˜ μš”μ²­ 감지 ν›„, μ•‘μ…˜μ„ 전달 λ°›μ•„ 쑰건 μ²˜λ¦¬ν•œ λ‹€μŒ κ²°κ³Ό κ°’μœΌλ‘œ stateλ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
const sinarioReducer = (state, action) => {
  if (action.type === 'ADD_TEXT') {
    console.log('ADD_TEXT μš”μ²­ 수락');
  }
  if (action.type === 'EDIT_TEXT') {
    console.log('EDIT_TEXT μš”μ²­ 수락');
  }
  if (action.type === 'DELETE_TEXT') {
    console.log('DELETE_TEXT μš”μ²­ 수락');
    console.log(action.payload);
    return state.filter((text) => text.id !== action.payload);
  }

  return state;
};

action

  • μ—…λ°μ΄νŠΈλ₯Ό μœ„ν•œ 정보 (μš”μ²­μ„œ 같은 것이닀 ) ,ν•„μš”ν•  경우 payload 전달
/* μ•‘μ…˜: μƒνƒœ μ—…λ°μ΄νŠΈ μš”μ²­μ„œ */ {
        type: 'DELETE_TEXT',
        payload: deleteId,
      }

dispatch

  • λ·°λ‘œλΆ€ν„° action 을 전달 λ°›μ•„μ„œ λ¦¬λ“€μ„œ ν•¨μˆ˜λ₯Ό 호좜(μ‹€ν–‰) ν•©λ‹ˆλ‹€
dispatch(ACTION_A);

initialZation

  • μƒνƒœ μ΄ˆκΈ°ν™”λ₯Ό 지연 처리 κ°€λŠ₯
  • 초기 계산 값을 μΆ”μΆœν•˜κ±°λ‚˜, μ–΄λ–€ λ™μž‘μœΌλ‘œ μƒνƒœλ₯Ό μ΄ˆκΈ°ν™” ν•  수 μžˆμŠ΅λ‹ˆλ‹€
const initialization = () => {
	// 계산이 ν•„μš”ν•œ 둜직
	return { ... };
};
profile
μ™œκ°€ λ””ν΄νŠΈκ°’μΈ ν”„λ‘ νŠΈμ—”λ“œ 개발자

0개의 λŒ“κΈ€