[fastcampus] Ch7. Hooks (1)

productuidev·2022년 3월 11일
0

React Study

목록 보기
14/52
post-thumbnail

패스트캠퍼스 한 번에 끝내는 프론트엔드 개발(Online) 강의 정리


Ch.7 Hooks (1)

Basic Hook

등장배경

클래스형 컴포넌트가 함수형 컴포넌트에 비해 가지는 단점때문

  • 클래스 문법이 어렵다.
  • 축소가 어렵다.
  • Logic의 재사용이 어렵다.
  • 최신 기술의 적용이 효과적이지 않다.

이러한 단점을 제외하고, 위에 언급한 state나 Life Cycle Method를 사용하기 위해서는 클래스형 컴포넌트 사용이 불가피했다. 하지만 Hooks가 등장하고 함수형 컴포넌트에서도 두 작업이 가능해졌다.
출처 - https://velog.io/@yangddu/React-Hook

  • 컴포넌트 사이에서 상태와 관련된 로직을 재사용하기 어렵습니다. (컨테이너 방식 말고, 상태와 관련된 로직)
  • 복잡한 컴포넌트들은 이해하기 어렵습니다.
  • Class는 사람과 기계를 혼동시킵니다. (컴파일 단계에서 코드를 최적화하기 어렵게 만든다)
  • this.state는 로직에서 레퍼런스를 공유하기 때문에 문제가 발생할 수 있다.

Functional Component = Stateless Component = Stateless Functional Component
Functional Component != Stateless Component (because of state hook)

함수형 컴포넌트에 사용되는 몇 가지 기술

상태 관리를 할 수 있는 useState (state)
렌더링 직후 작업을 설정하는 useEffect (effect)

useState

src/components/Example1.jsx

import React from "react";

export default class Example1 extends React.Component {
  state = { count: 0 };

  render() {
    const { count } = this.state;

    return (
      <div>
        <p>You clicked { count } times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );
  }

  click = () => {
    this.setState( {
      count: this.state.count + 1 } // 숫자가 올라가도록
    );
  };
}

src/components/Example2.jsx

import React from "react";

export default function Example2() {
    const [count, setCount] = React.useState(0); // 초기값 0

    return (
      <div>
        <p>You clicked { count } times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );

    function click() {
      setCount(count + 1); // count가 다시 실행되면서 숫자가 올라감
    }
}

src/components/Example3.jsx

import React from "react";

export default function Example3() {
    const [state, setState] = React.useState( {count:0} );

    return (
      <div>
        <p>You clicked { state.count } times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );

    function click() {
      // setState( {count : state.count + 1} );
      setState( (state) => { // setState가 다른 hooks와 사용할 경우 의존성
          return {
            count: state.count + 1,
          };
        };
      );
    }
}

src/App.js

import Example1 from "./components/Example1";
import Example2 from "./components/Example2";
import Example3 from "./components/Example3";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Example1 /> // class component
        <Example2 /> // function component (useState)
        <Example3 /> // useState
      </header>
    </div>
  );
}

src/components/Example4.jsx

import React from "react";

export default class Example1 extends React.Component {
  state = { count: 0 };

  render() {
    const { count } = this.state;

    return (
      <div>
        <p>You clicked { count } times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );
  }

  componentDidMount() {
    console.log('componentDidMount', this.state.count);
  }

  componentDidUpdate() {
    console.log('componentDidUpdate', this.state.count);
  }

  click = () => {
    this.setState( {
      count: this.state.count + 1 } // 숫자가 올라가도록
    );
  };
}

src/components/Example5.jsx

import React from "react";

export default function Example5() {
    const [count, setCount] = React.useState(0);

    React.useEffect( () => {
      console.log("componentDidMount"); // 최초 1번은 실행

      return () => {
        // cleanup
        // componentWillUnmount
        };
    }, []);

    React.useEffect( () => {
      console.log("componentDidMount & componentDidUpdate by count", count);

      return () => {
        // cleanup
        console.log('cleanup by count', count);
      },
    }, [count]); // 렌더와 밀접한 연관

    return (
      <div>
        <p>You clicked { count } times</p>
        <button onClick={this.click}>Click me</button>
      </div>
    );

    function click() {
      setCount(count + 1);
    }
}

src/App.js

import Example1 from "./components/Example1";
import Example2 from "./components/Example2";
import Example3 from "./components/Example3";
import Example4 from "./components/Example4";
import Example5 from "./components/Example5";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Example1 /> // class component
        <Example2 /> // function component (useState)
        <Example3 /> // useState
        <Example4 /> // log
        <Example5 />
      </header>
    </div>
  );
}

useEffect

sideEffect
side effect를 알아야 react hook 개념이 이해가 되고
그 hook 안에 useState와 useEffect가 속해있는 것이다.

React 컴포넌트가 화면에 1차로 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 흔히 Side Effect라고 한다. 예를 들어, 데이터를 가져오려고 외부 API를 호출할 때, 일단 화면에 렌더링할 수 있는 것은 1차로 먼저 렌더링하고 실제 데이터는 비동기로 가져오는 것이 권장된다. 왜 먼저 렌더링하냐면 연동된 API가 응답이 늦거나 없을 때 데미지(답답함)을 최소화 시켜 사용자 경험 측면에서 유리하기 때문이다.

→ 한마디로 요구되어지는 이펙트 이외에 다른 이펙트가 발생하는 현상이라고 생각하면 된다.
→ Hook은 이 side effect 를 수행하는역할을 한다. side effect 를 줄여 그냥 effect 라고 한다.
그래서 훅의 이름은 useEffect 가 된다.

출처 - https://devbirdfeet.tistory.com/52

function Counter() {
  const [count, setCount] = useState(0);

  useEffect( () => {
    document.title = `You clicked ${count} times`;
  });

  function click() {
    setCount (count + 1);
  }

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={click}>Click me</button>
    </div>
  );
}

useEffect 완벽 가이드

https://rinae.dev/posts/a-complete-guide-to-useeffect-ko

aha moment (특정 아이디어에 대해 영감을 얻게 되는 순간)

🤔 useEffect 로 componentDidMount 동작을 흉내내려면 어떻게 하지?
🤔 useEffect 안에서 데이터 페칭(Data fetching)은 어떻게 해야할까? 두번째 인자로 오는 배열([]) 은 뭐지?
🤔 이펙트를 일으키는 의존성 배열에 함수를 명시해도 되는걸까?
🤔 왜 가끔씩 데이터 페칭이 무한루프에 빠지는걸까?
🤔 왜 가끔씩 이펙트 안에서 이전 state나 prop 값을 참조할까?

Hooks를 통한 렌더링 이해

이펙트는 랜더링 결과의 일부

첫번째 렌더링

  • 리액트: state가 0 일 때의 UI를 보여줘.
  • 컴포넌트 : 여기 랜더링 결과물로 <p>You clicked 0 times</p> 가 있어.
    그리고 모든 처리가 끝나고 이 이펙트를 실행하는 것을 잊지 마:
    () => { document.title = 'You clicked 0 times' }.
  • 리액트: 좋아. UI를 업데이트 하겠어. 이봐 브라우저, 나 DOM에 뭘 좀 추가하려고 해.
  • 브라우저: 좋아, 화면에 그려줄게.
  • 리액트: 좋아 이제 컴포넌트 네가 준 이펙트를 실행할거야.
    () => { document.title = 'You clicked 0 times' } 를 실행하는 중.

클릭 후, 렌더링

버튼을 클릭하면 어떤 일이 벌어지는지

  • 컴포넌트: 이봐 리액트, 내 상태를 1 로 변경해줘.
  • 리액트: 상태가 1 일때의 UI를 줘.
  • 컴포넌트 : 여기 랜더링 결과물로 <p>You clicked 1 times</p> 가 있어.
    그리고 모든 처리가 끝나고 이 이펙트를 실행하는 것을 잊지 마: () => { document.title = 'You clicked 1 times' }.
  • 리액트: 좋아. UI를 업데이트 하겠어. 이봐 브라우저, 나 DOM에 뭘 좀 추가하려고 해.
  • 브라우저: 좋아, 화면에 그려줄게.
  • 리액트: 좋아 이제 컴포넌트 네가 준 이펙트를 실행할거야.
    () => { document.title = 'You clicked 1 times' } 를 실행하는 중.

참조자료

https://ko.reactjs.org/docs/hooks-intro.html#gatsby-focus-wrapper
https://surviveasdev.tistory.com/entry/React-hook%EC%9D%B4-%EB%82%98%EC%98%A8-%EC%9D%B4%EC%9C%A0%EC%99%80-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0
https://ko-de-dev-green.tistory.com/15


(강의 중간 회고)

지금 거의 강의를 중간 정도 들었는데, 일이 없을 때 너무 웹서핑만 하거나 그런 건 싫어서 시간 활용을 하고 싶어서 강의를 조금씩 수강하고 있다. 나중에 부트캠프나 학원에 가면 정식으로 배우겠지만 미리 선행학습 정도로 듣고 있는데 듣다보니.. 커리큘럼이 리액트 공식문서랑 다른 순서라(왜인지는 입문자라 모르겠지만)

설명이 다소 어렵다는 느낌이 든다..
오히려 참조자료를 더 많이 서칭하는 것 같아 다른 강의를 찾을까 고민중이다. (책으로 공부하더라도 개념에 대한 관점 설명이 다를 수 있어 같은 언어라도 여러 저자 책으로 학습하는 것이 좋다하는데...)

1. HTML/CSS/JavaScript
2. Git
3~4. JavaScript
5. TypeScript
6. SCSS
7. Bootstrap
8. Bundler
9. Vue.js
10. React (Basic)
11. Redux
12. React (+TypeScript)
13. mobX
14. GraphQL
15. Next.js
16. Svelte

이 강의는 Ch1~4,6,7,8 강사 분이랑 뒤에 강사분 총 2분인데,
앞의 강의는 내가 원래 알던 개념도 있지만 조금 더 입문자 난이도로 설명해주고,
뒤의 강의는 컴퓨터 공학개념도 설명해주시기도 하지만 난이도가 좀 어렵게 설명해주시는 거 같다.
(어제 나온 횡단관심사 개념 설명 듣다가 스프링까지 서칭하게됨..)

물론 이런 이론보다 실제 실습이 더 중요하지만
운영/유지보수 업무다보니 일 없을때 베이스라도 쌓을겸 듣는데...

약간 전형적인 개발자st 설명 느낌....

출처 - 웹툰 어느개발자 21화

그래서 참조자료 아티클 같은 걸 읽거나 포인트로 이해하고, 코드 작성하는 식으로 이해중인데

  • 한 챕터에 이해소요 시간이 너무 많은 것 같음
  • 실제 프론트엔드 실무에선 뒷부분 내용이 더 중요함

그래서 다른 강의로 추가로 더 사거나/변경할까 고민중...
이 얘기를 친구에게 했더니 친구 피셜.

강의나 책도 다 여러가지 강의가 있다고
일부러 어렵게 가르쳐야 배울 사람만 배우고 시장에 풀린다고.
쉽게 아는 개념이고 이해해서 기술자 수가 많아지면 안된다나 뭐래나..
일부러 강의나 책들 보면 다 허들이나 난이도를 조절한거라고..
(철저하게 프리랜서 마인드라 기술자 수가 많아지는 걸 싫어한닼)
profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글