ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ReactJS / calss와 function 의 비교, 그리고 Hello Hook
    DEV/REACTJS 2021. 12. 1. 23:08
    728x90
    반응형

    *생활코딩의 React class vs function style을 참조하였습니다*

     

    01. class VS function style

    React의 컴포넌트 선언에서는 class 선언과 function 선언 두 가지가 있다.

    class 선언의 경우 REACT의 기능을 full로 이용할 수 있지만 리액트의 문법을 잘 알아야 한다는 단점이 있다.

    class ClassStyle(){
      render(){
        return();
      }
    }


    의 형식으로 컴포넌트를 생성한다


    function 선언의 경우 REACT의 기능을 알지 못해도, 자바스크립트의 기본 문법을 통해 컴포넌트 구현이 가능하다.

    하지만 class 선언에서만 사용 가능한 몇 가지 기능을 사용하지 못하는데,
    대표적으로 state, lifecycle 등이 있다.

    function funcStyle(){
      return();
    }


    의 형식으로 컴포넌트를 생성한다.

    하지만 Hook 라는 기능을 통해, function style 선언도 class의 기능을 사용할 수 있게 되었다.

     

    02. Hook

    Hook는 갈고리라는 뜻인것 같은데, 어디선가 들었던 지식으로는 원래 React의 npm? 기능개발? 이었던것이였는데,
    리액트 팀이 Hook를 인수하고 정식적으로 발매(?)한 기능으로 알고 있다!
    (아마 노마드 코더 니콜라스의 강의를 듣다가 나온 내용일듯!)

    Hook 같은 경우에는 우선 여러가지가 있는데 오늘 배워볼 두 가지 중 첫 번째는 useState, 두 번째는 UseEffect이다.

     

    아래 링크에서 Hook에 대해 조금 더 자세히 볼 수 있다.

    https://ko.reactjs.org/docs/hooks-intro.html


    useState를 사용하기 위해서는
    react.useState 로 불러와서 그 내용을 사용하면 되지만,
    그렇게 하면 매번 불러와서 사용해야하는 번거로움이 있기 때문에
    리액트 문서를 처음 만들때



    로 먼저 불러와놓고 사용한다.

    useSate를 사용하면 기존 class에서의 this.props를 function style에서도 간단하게 사용할 수 있다.

    사용 방법은 다음과 같다.

    const [part, setPart] = useState("");


    내용을 설명하자면,

    useState는 배열 형식으로 두 개의 요소를 받아온다.
    로그를 확인해서 useState의 값을 확인해보면 첫 번째는 value(어떠한 값), 두번째 요소로는 함수가 등장하는 것을 볼 수 있다.
    다시 설명하자면 첫번째 값 part는 내가 useState에 설정한 값이라는 뜻이고, 그 초기값은 useState() 요 괄호안에 넣는 값이 들어간다.

    두번째 함수는 part를 바꾸기 위한 함수가 들어온다.
    보통 setPart() 로 해서 이 괄호안에 값을 넣으면 그 값이 part로 변경되는데
    이게 아주 유용하게 쓰인다.

     

    예를들어 함수를 

    const onClick = setPart((part) => part+1)

    이란 함수를 지정해두면

    내가 무언가  함수를 실행시킬때 마다 part의 값이 1씩 늘어나서 재정의되고

    다시 랜더링 되는 것이다!

     

    03.Componentmount

     

    여기서 더 자세한 내용을 볼 수 있다.

    https://ko.reactjs.org/docs/react-component.html


    React의 mount에 대해 알기 위해선 React 컴포넌트의 생성주기를 먼저 알아야한다.

    class를 통해 컴포넌트를 생성하면 각각의 메소드가 호출된다.

    ReactDOM.render()

    /getDefaultprops()
    /getinitialState()
    /componentWillMount()
      컴포넌트가 마운트(생성) 되기 전에 해야할 일이 있다면 이 매소드를 구현하는 것을 통해 필요한 코드를 넣어서
      컴포넌트가 생성되기 직전에(랜더전에) 이 함수를 실행하도록 하는 것

    /render()
      마운트 진행 (화면에 그려짐)

    /componentDidMount()
      그 다음에 해야할 일이 있다면 이 매소들을 넣는다

    <위는 컴포넌트가 구성되기 전의 초기작업>
    <퇴장할때 작업은 componentWillUnmount() 로 진행한다.>

    컴포넌트가 만들어진 뒤에 컴포넌트들의 변화(state 혹은 props)가 있을때마다 렌더 메소드가 호출되는데

    /shouldComponentupdate(nextProps, nextState)
      true라면 아래 메소드를 호출

    /componentWillUpdate(nextProps, nextSate)

    /render()

    /componentDidUpdate(prevProps, prevState)
      업데이트가 끝났다!



    순으로 호출이 된다.


    이 순서의 정해진 이름의 메소드를 호출하는것에 따라서 원하는 코드를 실행할수 되어있는 것이 class 방식이다.

    이게 원래 function 방식에서는 안됐는데 이게 Hook를 통해서 되는것이다!
    짱신기


    그것이 바로 useEffect다.

    useEffect도 useState를 사용할 때 처럼

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


    형식으로 불러온 후에
    useEffect( 함수(){
    },[])

    의 형식으로 사용한다.

    >optimizing performance by skipping Effect<

    원래 class 스타일의 컴포넌트 선언에서는

    componentDidUpdate(prevProps, prevState){
      if(prevState.count !== this.state.count){
        document.title = `You clicked ${this.state.count} times`;
      }
    }

    의 형식으로 컴포넌트 디드 업데이트를 사용했는데,
    만약 이전의 스테이트가 현재 스테이트와 다를때 이것을 실행하도록 하는
    성능과 효율성을 위한 함수를 만들어 사용하였다.

    이것을 useEffect에서도 똑같이 사용한다.

     

     

    useEffect(function () {
        console.log(
          "%cfunc => useEffect(componentDidMount & componentDidUpdate) " + ++funcId,
          funcStyle
        );
        //처음 랜더가 끝났을때 실행되고, 또 렌더가 될 때 실행된다.

        document.title = number + " : " + date;

        //unMount = return => 정리를 해주는 녀석을 cleanup이라고 하고 이렇게 구현함
        //컴포넌트의 퇴장씬
        //만약 다시한번 실행할때 정리하기 위해서 약속된 이 리턴값이 나온 후 다시 함수가 실행된다!
        return function () {
          console.log("%cfunc => useEffectReturn(unMount) " + ++funcId, funcStyle);
        };
      });

     

    import React, { useState, useEffect } from "react";
    import "./App.css";
    
    function App() {
      //히히히 강의듣기전에 아래 내용만 이해하고 혼자만든거임!!
      //언마운트를 실행시켜보려고 만든 코드라고 생각!
      const [show, setShow] = useState(true);
    
      const showClick = () => setShow(!show);
    
      //이런식으로 함수 실행시켜줘야지 무한 루프 안걸림
      //이 내용은 조금 더 찾아보기!
    
      return (
        <div className="container">
          <h1>Hello World</h1>
          <input onClick={showClick} type="button" value={show} />
          {show ? (
            <>
              <FuncComp initNumber={2} />
              <ClassComp initNumber={2} />
            </>
          ) : null}
        </div>
      );
    }
    
    const funcStyle = "color : blue";
    var funcId = 0;
    
    function FuncComp(props) {
      const [number, setNumber] = useState(props.initNumber);
      const [date, setDate] = useState(Date());
    
      //effect는 sideEffect의 줄임말
      //func comp가 호출되었을때 리턴되는 결과가 리액트 컴포넌트의 메인이다.
      //그것이 자신의 임무인데
      //그 임무에서 벗어나는 작업들! 예를들어 컴포넌트가 렌더링 끝난다음
      //컴포넌트의 어떤 정보를 변경시킨다던지 네트워크 통신을 하던지, 혹은 문서의 타이틀 값을 바꾼다던지
      //그럴때 쓩 등장
    
      //얘는 복수의 갯수를 설치도 가능하다.
    
      useEffect(
        function () {
          console.log(
            "%cfunc => useEffect Number(componentDidMount & componentDidUpdate) " +
              ++funcId,
            funcStyle
          );
          //처음 랜더가 끝났을때 실행되고, 또 렌더가 될 때 실행된다.
    
          document.title = number;
    
          //unMount = return => 정리를 해주는 녀석을 cleanup이라고 하고 이렇게 구현함
          //컴포넌트의 퇴장씬
          //만약 다시한번 실행할때 정리하기 위해서 약속된 이 리턴값이 나온 후 다시 함수가 실행된다!
          return function () {
            console.log(
              "%cfunc => useEffectReturn Number(componentDidMount & componentDidUpdate) " +
                ++funcId,
              funcStyle
            );
          };
        },
        [number]
      );
    
      useEffect(
        function () {
          console.log(
            "%cfunc => useEffect Date(componentDidMount & componentDidUpdate) " +
              ++funcId,
            funcStyle
          );
    
          document.title = date;
    
          return function () {
            console.log(
              "%cfunc => useEffectReturn Date(componentDidMount & componentDidUpdate) " +
                ++funcId,
              funcStyle
            );
          };
        },
        [date]
      );
    
      //배열안의 인자가 바뀌었을때만 첫번째 콜백함수가 호출되도록 한다. => 성능의 으마무시한 향상
    
      useEffect(
        //오직 디드 마운트에서만 실행되고 싶을 때
        function () {
          console.log(
            "%cfunc => useEffect (componentDidMount) " + ++funcId,
            funcStyle
          );
    
          document.title = date;
    
          return function () {
            console.log(
              "%cfunc => useEffectReturn (componentWillUnmount) " + ++funcId,
              funcStyle
            );
          };
        },
        []
        //이렇게 빈 배열을 전달하면 한번만 실행되고 그 이후에는 실행되지 않는다.
        //즉 한번만 실행
      );
    
      console.log("%cfunc => render " + ++funcId, funcStyle);
    
      return (
        <div className="container">
          <h2>function style component</h2>
          <p> Number : {number}</p>
          <p>Date : {date}</p>
          <input
            type="button"
            value="random"
            onClick={function () {
              setNumber(Math.random());
            }}
          />
          <input
            type="button"
            value="date"
            onClick={function () {
              setDate(Date());
            }}
          />
        </div>
      );
    }
    
    var classStyle = "color : red";
    //콘솔 로그에서 볼 서타일을 적용하기 위함
    
    class ClassComp extends React.Component {
      state = {
        number: this.props.initNumber,
        date: new Date().toString()
      };
    
      //메소드 호출
      componentWillMount() {
        console.log("%cclass => componentWillMount", classStyle);
        //이런식으로 작성하면 뒤의 있는 서타일이 적용된다.
      }
    
      componentDidMount() {
        console.log("%cclass => componentDidMount", classStyle);
      }
    
      shouldComponentUpdate(nextProps, nextState) {
        console.log("%cclass => shouldComponentUpdate", classStyle);
        return true;
      }
    
      componentWillUpdate() {
        console.log("%cclass => componentWillUpdate", classStyle);
      }
    
      componentDidUpdate() {
        console.log("%cclass => componentDidUpdate", classStyle);
      }
    
      componentWillUnmount() {
        console.log("%cclass => componentWillUnmount", classStyle);
      }
    
      render() {
        console.log("%cclass => render", classStyle);
        return (
          <div className="container">
            <h2>calss style component</h2>
            <p>Number : {this.state.number}</p>
            <p>Date : {Date()}</p>
            <input
              type="button"
              value="random"
              onClick={function () {
                this.setState({ number: Math.random() });
              }.bind(this)}
            />
            <input
              type="button"
              value="date"
              onClick={function () {
                this.setState({ Date });
              }.bind(this)}
            />
          </div>
        );
      }
    }
    
    export default App;
    반응형

    댓글

Designed by Tistory.