React

ReactJS - #5 기초 및 실습 (1주차)

행복하게사는게꿈 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 문법들을

 

사용할 수 있다.!!