โœ…ย Hooks API

๐ŸŒˆย ๊ฒฐ๋ก 

  • Hook์ด ์™œ ์ƒ๊ฒจ๋‚ฌ๋Š”์ง€ ์•Œ๊ณ  ์“ฐ์ž

โœ๏ธย ๋‚ด์šฉ

  • ์™œ Hooks API๊ฐ€ ์ƒ๊ฒจ๋‚ฌ๋‚˜?

HOC

  • ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ์žฌ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ React ๊ณ ๊ธ‰ ๊ธฐ์ˆ 
  • ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HOC)๋Š” React API์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ฉฐ, React์˜ ๊ตฌ์„ฑ์  ํŠน์„ฑ์—์„œ ๋‚˜์˜ค๋Š” ํŒจํ„ด

    const EnhancedComponent = higherOrderComponent(WrappedComponent);
    
    // ์‚ฌ์šฉ
    export default connect(mapStateToProps, mapDispatchToProps)(TodoApp);

Render Props

  • React ์ปดํฌ๋„ŒํŠธ ๊ฐ„์— ์ฝ”๋“œ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜ props๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๊ธฐ์ˆ 
  • ๊ตฌํ˜„๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์ฒด์ ์œผ๋กœ ๋ Œ๋”๋ง ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๋Œ€์‹ , React ์—˜๋ฆฌ๋จผํŠธ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ด๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ

    <DataProvider render={(data) => <h1>Hello {data.target}</h1>} />

SFC

class ClassComponent extends React.Component {
	render() {
		return <div>{this.props.name}</div>
	}
}

vs

const STatelessComponent = props = > <div>{props.name}</div>;

์ •๋ฆฌ

  • Hook ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

    import React, { useState, useEffect } from 'react';
    
    function Example() {
    	// State ๊ด€๋ฆฌ ์˜์—ญ
    	const [count, setCount] = useState(0);
    
    	// State๊ฐ€ ๋ณ€ํ–ˆ์„ ๋•Œ, ์ถ”๊ฐ€ ๋ Œ๋”๋ง ์ž‘์—… ์˜์—ญ
    	// componentDidMount, componentDidUpdate์™€ ๋น„์Šท
    	useEffect((
    		document.title = `You clicked ${count} times`;
    	) => {}, [])
    
    	return (
    		<div>
    			<p>You clicked {count} times</p>
    			<button onClick={() => setCount(count + 1)}>
    				Click Me
    			</button>
    		</div>
    	);
    }

โญ๏ธ ์š”์•ฝ

  • Hook ์ƒ๊ธด ์ด์œ ์™€ ๊ทธ ๊ณผ์ •์„ ์•Œ ๋•Œ, ์™œ Hook์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Œ

โœ…ย useEffect() ๊ธฐ๋ช…ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

๐ŸŒˆย ๊ฒฐ๋ก 

  • useEffect ์—๋Ÿฌ ํŒŒ์•…ํ•  ๋•Œ, ๊ธฐ๋ช…ํ•จ์ˆ˜ ์‚ฌ์šฉํ•˜๋ฉด ํŒŒ์•…ํ•˜๊ธฐ ์‰ฌ์›€

โœ๏ธย ๋‚ด์šฉ

  1. useEffect ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

    • ์—๋Ÿฌ ํŒŒ์•… cf) console.log, report, monitoring, React Devtools
    • ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๋„˜๊ธฐ๋ฉด ๋กœ๊ทธ์— ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ์ฐํžˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ ํŒŒ์•…์ด ์šฉ์ดํ•จ
// ๊ธฐ๋ช…ํ•จ์ˆ˜๋กœ ๊ฐ€์šฉํ•˜๊ธฐ
useEffect(
  function isInViewSomeComponent() {
    // some logic
  },
  [isInView],
);

useEffect(
  function onPopState() {
    if (navigationType === 'POP') {
      // some logic
    }
  },
  [isInView],
);

useEffect(function onInit() {
  // some logic
});

useEffect(function addEvent() {
  document.addEventListener();

  return function removeEvent() {
    document.removeEventListener();
  };
}, []);

โญ๏ธ ์š”์•ฝ

  • ๊ธฐ๋ช…ํ•จ์ˆ˜๋ฅผ ์ž˜ ์‚ฌ์šฉํ•ด์„œ ์—๋Ÿฌ ํŒŒ์•… ๋ฐ ์ฝ”๋“œ ํŒŒ์•…์„ ์šฉ์ดํ•˜๊ฒŒ ํ•˜์ž

โœ…ย ํ•œ ๊ฐ€์ง€ ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•˜๋Š” useEffect

๐ŸŒˆย ๊ฒฐ๋ก 

  • useEffect ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ, ํ•œ๊ฐ€์ง€์˜ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑํ•˜์ž.

โœ๏ธย ๋‚ด์šฉ

  • SRP - ๋‹จ์ผ์ฑ…์ž„ ์›์น™

    • ํ•˜๋‚˜์˜ ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค์ž โ‡’ useEffect()
    • ํ™•์ธ ํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ๊ธฐ๋ช… ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž
    • Dependency Arrays๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ๊ด€์ฐฐ ๋Œ€์ƒ์ด ๋“ค์–ด๊ฐ€๊ณ  ์žˆ๋Š”๊ฒŒ ์•„๋‹Œ์ง€ ํ™•์ธ
function LoginPage({ token, newPath }) {
  // โŒ ์œ„ํ—˜
  useEffect(() => {
    redirect(newPath);

    const userInfo = setLogin(token);
    // ... ๋กœ๊ทธ์ธ ๋กœ์ง
  }, [token, newPath]);

  // โœ… ๋ถ„๋ฆฌ

  useEffect(() => {
    redirect(newPath);
  }, [newPath]);

  useEffect(() => {
    const userInfo = setLogin(token);
    // ... ๋กœ๊ทธ์ธ ๋กœ์ง

    if (options) {
      // ๋ถ€๊ฐ€์ ์ธ ๋กœ์ง <= ์ถ”๊ฐ€ ๋™์ž‘ํ•ด๋„ ์ด์ƒ์ด ์—†๊ณ  ๋ถ€์ž‘์šฉ์ด ์ƒ๊ธธ ์ผ์ด ์—…์„ ๊ฒฝ์šฐ
    }
  }, [token, options]);
}

โญ๏ธ ์š”์•ฝ

  • useEffect ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ํ•œ ๊ฐ€์ง€ ์—ญํ• ๋งŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑํ•˜์ž.

โœ…ย Custom Hook ๋ฐ˜ํ™˜์˜ ์ข…๋ฅ˜

๐ŸŒˆย ๊ฒฐ๋ก 

  • React์—์„œ ์ œ๊ณตํ•˜๋Š” ์ปจ๋ฒค์…˜์— ๋งž๊ฒŒ Custom Hook์„ ์‚ฌ์šฉํ•˜์ž

โœ๏ธย ๋‚ด์šฉ

  1. Custom Hook ์‚ฌ์šฉ์‹œ ์ง€์ผœ์•ผ ํ•  ๊ทœ์น™๋“ค

    function ReturnCustomHooks() {
    	// โŒ
    	const [setValue, value] = useSomeHooks(true);
    
    	// โœ…
    	const [value, setValue] = useSomeHooks(true);
    
    
    	// โŒ
    	const [oneValue] = useSomeHooks();
    
     // โœ…
    	const oneValue = useSomeHooks();
    
    
    	// โŒ
    	const [firstValue, secondValue, _, thirdValue] = useSomeHooks(true);
    
     // โœ…
     const { firstValue, secondValue, rest} = useSomeHooks(true)
    
    
    	// โŒ
    	const query = useQuery({ queryKey: ['hello', queryFn: getHello })
    	const data = query.data;
    	const refetch = query.refetch;
    	const isSuccess = query.isSuccess
    
    	// โœ…
     const { data, refetch, isSuccess } = useQuery({ queryKey: ['hello', queryFn: getHello })
    }

โญ๏ธ ์š”์•ฝ

  • Custom Hook์„ ์‚ฌ์šฉํ•  ๋•Œ, ์ผ๊ด€๋œ ์ปจ๋ฒค์…˜์„ ์ž‘์„ฑํ•˜์ž.

โœ…ย useEffect ๋‚ด๋ถ€์˜ ๋น„๋™๊ธฐ ํ•จ์ˆ˜

๐ŸŒˆย ๊ฒฐ๋ก 

  • useEffect ์‚ฌ์šฉ์‹œ Promise ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ์‚ฌ์šฉ์‹œ ์ฃผ์˜ํ•˜์ž

โœ๏ธย ๋‚ด์šฉ

  1. useEffect ๋‚ด๋ถ€์—์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜ ์ฒ˜๋ฆฌ

    // โŒ
    // useEffect ๋ฆฌํ„ด ๊ฐ’์€ undefined์ด๊ฑฐ๋‚˜ clean function์ž„
    useEffect(async () => {
     // ๋น„๋™๊ธฐ ์ž‘์—…
     const result = await fetchData();
    }, []);
    
    // โœ…
    useEffect(async () => {
     // ๋น„๋™๊ธฐ ์ž‘์—…
     const fetchData = async () => {
       const result = await someFetch();
     };
    
     fetchData();
    }, []);

โญ๏ธ ์š”์•ฝ

  • useEffect ๋‚ด๋ถ€์—์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ปค์Šคํ…€ ํ›…์ด๋‚˜, ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์ž

์ฐธ๊ณ