본문 바로가기
학원에서 배운 것/React

KDT 5th 웹개발자 입문 수업 36일차

by 쿠리의일상 2023. 3. 27.

JSX 문법

JSX 는 결국 Babel 에 의하여 JS 로 번역이 되므로

 

1. class -> className

기존 DOM 요소에 class 를 부여할 때 쓰던 class 를 className 이라고 써야 한다. (class 는 키워드이므로)

 

2. 데이터 바인딩이 용이

원래 HTML 은 정적인 페이지를 구현하는데 사용이 되었지만 현대의 웹은 서버와 통신을 하여 변경해줄 필요가 있으며 이 경우 DOM 에 JS로 접근하는 document.getElementById() 등을 사용해줘야 하지만, JSX를 사용하면 HTML 요소는 return () 안에, JS의 경우 { } 안에 써주면 된다.

 

3. JS 는 { } 안에 써준다. 대부분의 JS 문법을 사용할 수 있지만, 예외적으로 if 문 등은 불가능하다.

❥ 함수를 넣을 때는 바로 호출될 수 있도록, {함수명()} 으로 기재하거나 이벤트 리스너 함수일 경우는 {함수명} 으로 기재

❥ 이미지는 src 폴더 안에 관리하며, import 하여서 { } 안에 넣어서 전달 가능

if 문은 안되지만 삼항 연산자( ? : ) 는 가능

 

4. 인라인 스타일은 객체로 넣어줘야 한다.

const Inline = () => {

  const style = {
    fontSize : {
      fontSize : '30px',
    },

    textAlign : {
      textAlign: 'center',
    }
  }
  return (
    <div style={style.fontSize}>
      인라인 스타일
    </div>
  )
}

export default Inline;

 

<div style={style.fontSize}>
      인라인 스타일
</div>

여기서 style 속성에 속성값을 {style.fontSize, style.textAlign} 형태로 여러개 넘겨줄 수 없다.

인라인 스타일의 경우, 하나의 객체에 스타일을 담아줘야한다.

 

 

객체로 스타일을 작성할 때 케밥 케이스의 - 기호를 빼기 연산자로 받아들이므로 kebab-case 에서 camelCase 로 스타일 속성명을 바꿔서 작성해줘야 한다!

 

5. 이벤트 핸들러

기존의 JS 에서는 DOM 요소에 대한 이벤트를 컨트롤하는 방법으로 DOM 요소에 onclick 이나 addEventListener 를 사용했으나,

리액트에서는 onClick 을 써준다.

onClick = { JS 코드 }

const EventHandler = () => {
  return (
    <span onClick={() => {
      alert('이벤트 핸들러');
    }}>Click</span>
  )
}

export default EventHandler;

함수를 바로 호출해줘야 하는 경우가 아니라면 함수를 정의해줘서 넘겨주는 것이 좋다.

 

7. 디버그 용이성

기존 JS 에선 console 창을 띄워봐야겠지만 리액트는 치명적 버그일 경우 화면에 바로 띄워버린다. (warnning은 console에 나타남)

리액트는 기존 JS의 문제점을 보완하고자 프레임워크 레벨에서 자체적으로 strict 모드를 강제한다.

 

 

State

상태를 나타내는 변수

즉, 리액트에서 컴포넌트에 대한 상태를 의미함

state 가 변경되면 해당 컴포넌트는 바로 다시 렌더링 되기 때문에 컴포넌트의 유동성 관리가 쉽다.

-> 상태관리는 Redux

 

useState

앞서 state 가 변경되면 리액트에서 해당 부분을 바로 리렌더링하는데,

이러한 특성을 활용하여 쉽게 변경 사항을 HTML 반영이 가능하다.

import { useState } from 'react';

const [ state변수명, state를 변경할 함수명 ] = useState(state초기값);
---
const [state, setState] = useState(initialState);

state 가 이전 값과 달라지면 해당 컴포넌트를 재렌더링해준다.

하지만 강제로 state를 변경해주면 재렌더링이 되지않는다. 오로지 useState 에 선언해준 상태 변경 함수로 state를 변경해야만 리액트가 state 변경을 알아차리고 html 을 변경해준다.

import React from 'react'
import { useState } from 'react';

export default function State2() {
  let [strState, setStrState] = useState('init');
  
  // state 강제 변경 -> 리렌더링이 일어나지 않음
  function changeState() {
    strState += '-';
    console.log(strState);
  }

  return (
    <div>
      <button onClick={() => setStrState(strState +'+')}>리렌더링 반복!</button>
      <button onClick={() => changeState()}>State 강제 변경</button>
      <br />
      <span>{strState}</span>
    </div>
  )
}

 

상태 변경 함수는 꼭 함수 정의를 하고 사용해준다.

return 내부에서 함수를 정의하지 않고 바로 상태 변경 함수를 호출하면 클릭이 안되어도 실행이 되기에

state 가 변경되면 return 내부에 있는 요소를 재렌더링 해야하니 return 호출

-> 다시 상태 변경 함수 호출 -> return 호출의 무한 루프 -> ...

결국 무한 루프에 빠지게 된다.

그래서 상태 변경 함수는 return 에서 익명함수로 정의해서 사용해준다.

 

또는, 상태 변경 함수를 포함한 함수로 만들어서 호출해주면 무한 루프에 빠지는 것을 막을 수 있다.

  let [strState, setStrState] = useState('init');

  function customSetStrState() {
    strState +='+';
    setStrState(strState);
  }

 

카운트 만들기

import {useState} from 'react'

export default function Counter() {
  const [count, setCount] = useState(0);
    
  return (
    <div>
      <span>{count}</span> <br/>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

 

 

리액트에 3항 연산자 사용해보기

state 를 변경하면 컴포넌트가 리렌더링 된다.

state 가 변경될 때 다른 걸 변경하면, 리렌더링이 일어나면서 스무스하게 변경이 된다.

import {useState} from 'react'

export default function ConditionEx() {
  const [count, setCount] = useState(0);
  const style = {
    icon : {
      fontSize : '62px',
      border :'none',
      backgroundColor : 'white',
    }
  }
  return (
    <div>
      <button 
        style={style.icon}
        onClick={() => setCount(count + 1)}>
          { count >= 10 ? '🥳': '👍' }
      </button>
      <br/><span>{count}</span>
    </div>
  )
}

 

 

클래스형 컴포넌트의 State

클래스형 컴포넌트는 Component 라는 클래스를 상속하여 사용해야 하므로 Component 를 import 해야한다.

클래스에서 사용하는 생성자에 state 값을 지정하고 this.state 라는 객체에 변경하고자 하는 값을 저장

 

그리고 this.setState() 를 사용하여 this.state 라는 객체에 저장된 값을 변경해주며 사용하며 state 에 변경이 일어나면 컴포넌트는 알아서 재렌더링 된다.

import React, { Component } from 'react';

export default class ClassState extends Component {
	constructor(props) {
    	super(props);
        this.state = {
        	state명: state초기값,
        };
    }
    
    render() {
    	const { state명 } = this.state;
        
        return (
        	<div>
            	<button onClick={() => this.setState({ state명 : state변경값 })}></button>
            </div>
        );
    }
}

 

 

함수형 컴포넌트의 State 

함수형 컴포넌트의 초창기엔 리액트의 핵심 기능인 State 와 Lifecycle 을 쓸 수 없었지만 리액트 16.8 버전 이후부터

Hooks 라는 메서드를 제공하여 함수형 컴포넌트에서도 핵심 기능들을 사용이 가능해졌다.

 


 

State 와 변수 비교

import {useState} from 'react'

export default function StateAndVariable() {
  // State
  let [state, setState] = useState(0);
  
  // 변수
  let variable = 0;
  function setVariable() {
    variable += 1;
    console.log(`state : ${state} / variable : ${variable}`);
  }

  return (
    <div>
      <h1>{state} / {variable}</h1>
      <button onClick={() => {
        setState(state += 1);
        setVariable();
      }}>+ 1</button>
    </div>
  )
}

variable 값은 state 안에 정의 되어 있고, 컴포넌트는 state 가 변경되었을 때 리렌더링 되므로 변수가 그때마다 재정의 되므로 수가 늘어나지 않는 것이다.

즉, 컴포넌트에 값을 기억시키는 것은 위험한 행동이다.