ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ReactJS - #5 기초 및 실습 (1주차)
    React 2020. 12. 17. 14:31

    Class Component

     

    [Class.js]

    import React, { Component} from 'react'
    
    // state 기능 및 라이프 사이클 기능을 사용
    // render 함수가 반드시 필요(class형 Component에서)
    
    class ClassComponent extends Component{
        // 생성자 함수 
        // 생성자가 이유는 props나 state같은 상태값들을 초기화하기 위해서
        constructor(props){
            // constructor를 사용하면 항상 병용, this를 초기화, props를 넣어줘야 this.props 사용가능
            // suepr(props)를 통해서 this를 초기화 해주지 않으면 다른 component에서 사용했던 this와 충돌이 발생할 가능성이 있다.
            // super() 이렇게 props를 파라미터로 안주고도 할 수 있는데 그럼 props를 쓸 수가 없다. 
            super(props) 
            // initial state를 선언
            // this.state = {} 이 과정을 통해 component내의 render 함수에서 key값에 접근할때 this.state.key가 아닌 key로 접근가능
            this.state = {
                key : 'initialValue'
            }
    
            // event binding
    
            // this를 쓰기 위함이라고 생각하면 되는데 this에 묶여져 있는 event가 우리가 밑에 선언한 이벤트와 묶여서 바인딩이 된다 ?
            // 흠.. 잘 이해가 안되는데 근데 이건 Class Component에만 존재하고 function Component에는 없다.
    
            this.handleClick = this.handleClick.bind(this)
            console.log('constructor')
        }
    
        static defaultProps = {
            name : '홍길동'
        }
    
        handleClick(){
            // event binding을 안시켜놓으면 여기에서 this가 state를 가리키지 않아서 오류가 발생한다.
            this.setState({ key : 'value2'})
        }
    
        componentWillMount(){
            console.log('componentWillMount') // DOM이 생성되지 않은 단계, setState 실행 x
        }
    
        componentDidMount(){
            // 외부 데이터 가져오기
            // this.setState({})
            console.log('componentDidMount') // DOM이 생성된 단계, setState를 통해 DOM의 제어가 가능
        }
    
        componentWillReceiveProps(nextProps){
            console.log('componentWillReceiveProps');
        }
    
        shouldComponentUpdate(nextProps, nextState){
            console.log('shouldComponentUpdate');
            return true;
        }
    
        componentDidUpdate(prevProps, prevState){
            console.log('componentDidUpdate');
        }
    
        // componentDidCatch(){
            // 에러 핸들링
        //}
    
        render(){
            // render() 함수를 통해 props를 조회
            // 비구조화 할당 방식으로 state와 props 사용 가능
            const { key } = this.state;
            const { name } = this.props;
            console.log('render')
    
            return(
                <div>
                    <h1>클래스형 컴포넌트</h1>
                    <h2>{ key }</h2>
                    <h2>{ name }</h2>
                    <button onClick={this.handleClick}>클릭</button>
                </div>   
            );
        }
    }
    
    export default ClassComponent;

    * 메소드에 대한 세부내용은 주석 참고


     

    Function Component

    import {useState, useEffect} from 'react';
    
    // state 기능 및 라이프 사이클 기능을 사용할 수 없음 (stateless) 그래서 hook이 나오기전까지 class Component 사용 권장
    // 리액트 버전 16.8부터 Hook이 등장 -> state, lifeCycle 기능 대체가능
    // 클래스형 컴포넌트보다 간단
    // 클래스형 컴포넌트보다 메모리 자원을 적게 사용
    // -> 최근에는 function Component 사용 권장
    
    // 비구조화 할당으로 props 사용 가능
    
    const FuntionalComponet = (props) =>{
    
        const [name, setName] = useState('홍길동');
        //     설정한 state, setState({key : value}) -> setKey(value)의 구조
        // useState('홍길동') -> initalize
    
        const handleClickBtn = (val) => {
            setName(val);
        }
    
    
        useEffect(() =>{
            console.log('component did update');
            // return () =>{
            //     console.log('component will mount');
            // }
        }, []);
    
    
        // Class Component와 다르게 render()가 없고 return으로 바로 들어감 
        //  return이라는 부분안에서 state같은 상태값들을 포함한 html 태그들을 사용하는게 JSX
        return (
            <div>
                <h1>함수형 컴포넌트</h1>
                <h2>{ name }</h2>
                <button onClick ={()=>setName('김철수')}>변경</button>
    
                {/* onClick={} 이안에 왜 에로우 펑션을 써야되나? */}
                {/* () => handleClickBtn('김철순') */}
                {/* handleClickBtn('김철순') */}
                {/* 위 두개의 차이점이 무엇인가 봤을때 파라미터로 어떤 값을 던져줄경우 반드시 funtion의 형태로 만들어줘야 하기때문에 ()=> fution('val') 의 형태로 만들어주어야 하고 */}
                {/* 파라미터가 없이 그냥 값을 가져오기만 하는 경우에는 handleClickBtn 까지 ()를 생략한 것을 onClick에 넣어주면 정상적으로 실행됨 */}
                <button onClick ={()=>handleClickBtn('김철순')}>변경</button>
            </div>
        )
    }
    
    export default FuntionalComponet;

    * 세부 내용은 주석 참고


    위의 function Componet를 세부적인 Component로 쪼개 보자!

     

    components 폴더를 만들고 그 안에 name.js 파일을 만든다.

     

    [name.js]

     

    [functional.js]

    이렇게 구조를 나눠주면 각각 다른 파일의 js이지만 한페이지에서 바꾸는 것처럼 페이지가 동작한다.

     

    또한, button의 onClick에서 실행되는 callback funtion은 functional의 state 즉, 상위 component의 state를 바꾸는

     

    funciton을 수행하는데, 이 상위의 component의 state를 바꾸는 것만으로도 하위의 Component에서 영향을 받아 

     

    자동으로 수정되는 구조를 가진다.!!

     


     

    주의해야 할 건 name.js에서 사용하는 props.name 같은 props는 수정할 수 없다는 점!

     

    props의 값을 바꾸려면 부모 Component의 state를 수정해서 자식 Component가 받는 props의 값을 수정해야하는 

     

    구조를 반드시 이해해야한다.

     

    [name.js]

    const NameComp = (props) => {
    
        const handelClickBtn = (val) =>{
            props.onClickCB(val)
        }
        return (
            <div>
            <h2>
                {props.name}    
            </h2>
             <button onClick={()=>handelClickBtn('하위 컴포넌트')}>변경</button>
            </div>
        );
    }
    export default NameComp;

     

    [functional.js]

    return (
            <div>
                <h1>함수형 컴포넌트</h1>
                {/* <h2>{ name } </h2> */}
                <Name name={ name }
                      onClickCB={handleClickBtn}/>
                <button onClick ={()=>setName('김철수')}>변경</button>
    
                {/* onClick={} 이안에 왜 에로우 펑션을 써야되나? */}
                {/* () => handleClickBtn('김철순') */}
                {/* handleClickBtn('김철순') */}
                {/* 위 두개의 차이점이 무엇인가 봤을때 파라미터로 어떤 값을 던져줄경우 반드시 funtion의 형태로 만들어줘야 하기때문에 ()=> fution('val') 의 형태로 만들어주어야 하고 */}
                {/* 파라미터가 없이 그냥 값을 가져오기만 하는 경우에는 handleClickBtn 까지 ()를 생략한 것을 onClick에 넣어주면 정상적으로 실행됨 */}
                <button onClick ={()=>handleClickBtn('김철순')}>변경</button>
            </div>
        )

     

    이런식으로 상위 Component의 handleClickBtn이란 메소드를 하위 Component에 전달해서 하위 컴포넌트의 버튼을

     

    클릭하면 상위 Component의 state를 수정하는 메소드가 작동하게 하는 구조!!

     

     

     


    자 여기서 한번 정리해보자

     

    react hook을 쓰려면 이렇게 import해주어야 되고

    import { useState } from 'react';

     

     

     

    하위 컴포넌트들을 사용하려면 상위 컴포넌트에서 import 해야하는데 

    import Name from '../components/name';
    import Job from '../components/job';

    이렇게 import해주면 되는데 Component를 import 하기전에 필수적으로 선행되어야 하는 순서는

     

     

    각각의 하위 component에서 export default를 선언해주어야 한다는 것이다.

    export default JobComp;

     

    또한 hook을 사용하는 구조는 

    이런식으로 사용하게 되고 배열의 첫번째 인덱스에는 값이 저장될 장소, 두번째 인덱스는 저장된 값을 컨트롤하는 메소드이다.

     

     

     

    또한

     

    상위 컴포넌트에서 import한 하위컴포넌트를 사용할 때는 <Name /> 이런 형태로 사용하며

     

    값을 직접 던져줄 수 있다.

     

    그럼 이렇게 상위 component에서 던져준 job과 onClickCB를 props로 받게 되는데

     

    밑의 코드에서는 비 구조 할당 방식으로 필요한 값들을 할당해서 사용하였다

     

    또한 JSX에서는 html문과 함께 script 문도 사용할 수 있기 때문에 { } 안에서 아래와 같이 삼항연산자 따위의 script 문법들을

     

    사용할 수 있다.!!

    'React' 카테고리의 다른 글

    ReactJS - #3 기초 및 실습 (2주차)  (0) 2020.12.20
    ReactJS - #1 기초 및 실습 (2주차)  (0) 2020.12.17
    ReactJS - #4 기초 및 실습  (0) 2020.12.16
    ReactJS - #3 기초 및 실습  (0) 2020.12.16
    ReactJS - #2 기초 및 실습  (0) 2020.12.16

    댓글

Designed by Tistory.