본문 바로가기
IT/엘리스 AI 트랙

[엘리스 AI 트랙 2기] 7주차-React 기초 (08/03)

by 무녈 2021. 8. 3.

자료의 출처는 '엘리스 AI 트랙 2기 (https://aitrack.elice.io/)' 'React 기초'이며, 학습 후 정리한 내용입니다.

⚡️올바르지 않은 내용이 있을 경우 댓글로 남겨주시면 감사하겠습니다.⚡️


 

1. Props와 State

01. Props

Props

 

컴포넌트 생성

const Welcome = (props) => {
	return <h1>Hello, {props.name} </h1>;
}

컴포넌트 사용

const App = () => {
	return <div>
    	<Welcome name="수영" />
        <Welcome name="민수" />
        <Welcome name="영희" />
    </div>
}

 

기본적으로 Component에 원하는 값을 넘겨줄 때 사용하며
넘겨줄 수 있는 값은 변수, 함수, 객체, 배열 등 JavaScript의 요소라면 제한이 없다.

주로 Component의 ‘재사용’을 위하여 사용한다.

Props는 읽기 전용

Props의 값을 임의로 변경해서 사용해선 안된다.
const Welcome = (props) => {
	props.name = props.name + '님';
    return <h1>Hello, {props.name}</h1>;
}

Props의 값을 변경해서 사용하고 싶다면, 새로운 변수를 생성한다.

const Welcome = (props) => {
	const username = props.name + "님";
    return <h1>Hello, {username}</h1>;
}

DOM Element의 Attributes

  • 기본적인 DOM Element(div, span 등)들의 Attribute는 camel case로 작성
    예: tabIndex, className 등
  • ‘data-’ 또는 ‘aria-’ 로 시작하는 Attribute는 예외
    예: data-type, aria-label 등
  • HTML의 Attribute와 다른 이름을 가지는 Attribute
    예: class → className, for → htmlFor 등
  • HTML의 Attribute와 다른 동작 방식을 가진 Attribute
    예: checked(defaultChecked), value(defaultValue), style 등
  • React에서만 쓰이는 새로운 Attribute
    예: key, dangerouslySetInnerHTML 등
style: string아 아니라 object 형식으로 적어야함.
checked와 value는 input element에서 사용되는데, 기존 html에서는 이 값들을 설정하면 기본값을 설정하는 역할을 하게되는데, react에서는 조금 다르게 작동 value값을 적용하면 기본값이 아니라 그 값으로 딱 고정이됨.
만약 기본값을 설정하고 input을 자유롭게 설정하고자 한다면 defaultValue, defaultChecked 사용

key: array에 있는 값들을 표현할 때 사용, 리액트가 값을 인지하기 용이하도록 도와주는 값
dangerouslySetInnerHTML: 잘 사용할 일 x, string을 html로 변환할 때 사용

HTML과 다른 방식의 React Attribute(checked, value)

(<input type="checkbox" checked={false} />)

 

HTML에서 checked 또는 value는 해당 값이 ‘초기값’으로 쓰이지만
React 내에서는 현재 값을 의미
즉, 위 예시처럼 checked 값이 false로 고정돼있는 경우에

사용자가 checkbox를 클릭하여도 값의 변화가 일어나지 않는다.


만약 ‘초기값’의 의미로 checked 또는 value를 사용하고 싶다면 defaultChecked, defaultValue Attribute를 설정

React에서만 쓰이는 새로운 Attribute(key)

const name = () => {
	const names = [
    	{ key: '1', value: '민수' },
        { key: '2', value: '영희' },
        { key: '3', value: '길동' },
    ]
   	return (
    	<div>
        	{names.map((item) => {
            	<li key={item.key}>{item.value}</li>
            })}
        </div>
    )
}

(참고: map 활용)

Key는 React가 어떤 항목을 변경, 추가 또는 삭 제할지 식별하는 것을 돕는다.
Key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 Element에 지정해야 한다.

Key는 배열 안에서 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없다.

두 개의 다른 배열을 만들때 동일한 key를 사용할 수 있다.

02.State

state

import { useState } from 'react';

function Example() {
	const [count, setCount] = useState(0);
    return (
      <div>
    	<p>버튼을 {count}번 눌렀습니다.</p>
        <button onClick={() => setCount(count + 1)}
        	클릭
        </button>
      </div>
    )
}

 

import React, ( useState ) from "react";
function Test() {
	const [변수이름, 변수에 값을 설정하는 함수 이름] = useState(초기값);
}

StateComponent 내에서 유동적으로 변할 수 있는 값을 저장

개발자가 의도한 동작에 의해 변할 수 도 있고 사용자의 입력에 따라 새로운 값으로 변경될 수 도 있다.

State 값이 변경되고 재렌더링이 필요한 경우 에 React가 자동으로 계산하여 변경된 부분을 렌더링한다.

 

state

컴포넌트 내에서 관리하는 변수

렌더링이 일어나도 유지되는 변수

함수 컴포넌트 useState()
클래스 컴포넌트 this.state

컴포넌트 내에서 변수를 변수처럼 사용할 수 없는 이유

ex) 사용 불가 소스

function Test() {
	let clickCount = 0;
	
    function handleClick() {
    	clickCount += 1;
	}
	return (
		<div> 
        	<input
				type=“button value=“버튼”
				onClick={handleClick} 
            />
			<p>{clickCount}</p> 
        </div>
	) 
}

렌더링 시 해당 컴포넌트가 계속 실행됨

<Test /> == Test()

함수가 실행될 때마다 내부 변수가 초기화 됨

=> 즉 컴포넌트가 렌더링 될 때마다 변수가 초기화 돼 사용 불가

하지만 State는 렌더링이 돼도 값을 유지!

렌더링이 되는 경우
- 부모 컴포넌트가 렌더링 됐을 때
- props가 변경됐을 때
- state가 변경됐을 때

State 값을 직접 변경하지 않는다. 

import {useState} from 'react';

function Example() {
    let [count, setCount] = useState(0);
    return (
        <div>
            <p>버튼으르 {count번 눌렀습니다.}</p>
            <button onClick={() => {
                count = count + 1;
            }}>
                클릭
            </button>
        </div>
    )
}

 

State 값을 직접 변경하게 되면 ReactComponent를 다시 렌더링할 타이밍을 알아 차리지 못한다.
반드시 setState 함수를 이용해 값을 변경한다.

setState 함수를 호출할 때 React에게 “다 시 렌더링 해주세요~” 라는 명령이 내려진다.

State를 변경하는 두 가지 방법

1. setState 내에 변경할 값을 넣기

const [count, setCount] = useState(0);
setCount(count + 1);

2. setState에 함수를 넣기

const [count, setCount] = useState(0);
setCount((current) => {
    return current + 1
})

 

setState 함수에는 변경할 값을 직접 넣는 방법이 있고, 함수를 넣는 방법이 있다.

함수를 넣는 경우 함수가 반환(return)하는 값으로 State가 변경된다.
위 예시처럼 현재 값을 기반으로 State를 변경하고자 하는 경우 함수를 넣는 방법을 권장

Object를 갖는 State를 만들 때 주의사항

const [user, setUser] =
useState({name: "민수", grade:1})
setUser((current) => {
    current.grade = 2;
    return current;
})

 

예시와 같이 Object를 값으로 같는 State도 만들 수 있다.

그러나 예시의 경우 ReactState의 변경을 감지하지 못한다!

user object 안의 grade가 변경되었지만 user 자체는 변경되지 않았기 때문

 

user의 grade가 변경되었지만 user의 내용을 담는 object 자체가 변경된 것은 아니다.

=> 기존 user의 내용을 새로운 object에 담고 grade를 변경한다.

const [user, setUser] =
useState({name: "민수", grade:1})
setUser((current) => {
    const newUser = {...current}
    newUser.grade = 2
    return newUser;
})

2. 이벤트 처리

01. 이벤트 소개

이벤트

이벤트(event)란 웹 브라우저가 알려주는 HTML 요소에 대한 사건의 발생을 의미

유저의 행동에 의해 발생할 수도 있으며 개발자가 의도한 로직에 의해 발생할 수도 있다.

이렇게 발생된 이벤트를 자바스크립트를 이용해 대응할 수 있다.

Element가 로딩되었을 때, 사용자가 Element를 클릭했을 때, 마우스를 올렸을 때, 더블 클릭했을 때, 키보드 입력을 주었을 때 등 다양한 이벤트가 존재

이벤트 핸들러 함수에서는 다양한 로직을 처리하고 그 결과를 사용자에 출력하여 알릴 수도 있다.

 

핸들링 함수 선언

const App = () => {
    const handleClick = () => {
        alert('클릭했습니다.');
    }
    return (
        <div>
            <button onClick={handleClick}>클릭하세요</button>
        </div>
    )
}

익명 함수로 처리

const App = () => {
    const handleClick = () => {
        alert('클릭했습니다.');
    }
    return (
        <div>
            <button onClick={() => {alert('클릭했습니다.')}
            }>클릭하세요</button>
        </div>
    )
}

 

React에서 이벤트를 처리하는 방법은 크게 두 가지 방법

별도의 핸들링 함수를 선언하고 Element에 넘겨주는 방법

이벤트를 할당하는 부분에서 익명 함수를 작성하는 방법

이벤트 객체

const App = () => {
    const handleClick = (event) => {
        console.log(event.target.value + '라고 입력하셨네요.');
    }
    return (
        <div>
            <input onChange={handleChange} />
        </div>
    )
}

(참고: https://developer.mozilla.org/ko/docs/Web/API/Event)

  • DOM Element의 경우 핸들링 함수에 이벤트 object를 매개변수로 전달
  • 이벤트 object를 이용하여이 벤트 발생 원인이벤트가 일어난 Element에 대한 정보를 얻을 수 있다.
  • 이벤트 형태(클릭,키 입력 등)와 DOM 종류(button, form, input )에 따라 전달되는 이벤트 object의 내용도 다르니 유의

많이 쓰이는 DOM 이벤트

onClick: Element를 클릭했을 때
onChange: Element의 내용이 변경되었을 때(input의 텍스트를 변경, 파일 선택 등)

onKeyDown, onKeyUp, onKeyPress: 키보드 입력이 일어났을 때

onDoubleClick: Element를 더블 클릭했을 때
onFocus: Element에 Focus되었을 때
onBlur: Element가 Focus를 잃었을 때
onSubmit: Form Element에서 Submit 했을 때

02. 컴포넌트 내 이벤트 처리

DOM 버튼 클릭

const App = () => {
  const handleClick = () => {
    alert("클릭했습니다."); 
  }
  return (
    <div>
 	  <button onClick={handleClick}>클릭하세요</button> 
    </div>
  ); 
};

 

DOM element의 클릭 이벤트를 전달받아 처리하는 간단한 예제

DOM Input 값을 State에 저장하기

const App = () => {
    const [inputValue, setInputValue] =
    useState("defaultValue");

    const handleChange = (event) => {
        setInputValue(event.target.value);
    }

    return (
        <div>
            <input onChange={handleChange}
            defaultValue={inputValue} 
            />
            <br />
            입력한 값은: {inputValue}
        </div>
    );   
}

 

event object의 target은 이벤트의 원인이 되는 Element를 가리킨다.

현재 event의 target은 input element이므로 입력된 value를 가져와 setState를 하는 모습

여러 Input 동시에 처리하기

const App = () => {
    const [user, setUser] = useState({ name; "민수",
    school: "엘리스대학교" });
    const handleChange = (event) => { 
    	const { name, value } = event.target;
	    const newUser = { ...user }; 
    	newUser[name] = value; 
        setUser(newUser);
    };
    
    return (
      <div>
        <input name="name" onChange={handleChange} value={user.name} />
        <br />
        <input name="school" onChange={handleChange} value={user.school} />
        <p>
          {user.name}님은 {user.school}에 재학중입니다.    
        </p> 
      </div>
    ); 
};

 

State를 여러 개 선언할 수도 있지만 object를 활용하여 여러 개의 input을 state로 관리하는 방법이 있다.

target으로부터 name을 받아와 해당 namekey에 해당하는 value를 변경하여 state에 반영

03. 다른 컴포넌트로 이벤트 전달

컴포넌트간 이벤트 전달하기

const MyForm = ({ onChange }) => {
    return (
        <div>
            <span>이름: </span>
            <input onChange={onChange} />
        </div> 
    )
}
const App = () => {
    const [username, setUsername] = useState('') 
    return (
        <div>
            <h1>{username}님 환영합니다.</h1> 
            <MyForm
                onChange={(event) => {
                setUsername(event.target.value)
                }}
             />
        </div> 
    )
}

 

사용자가 입력한 정보를 현재 컴포넌트가 아닌 부모 컴포넌트에서 활용해야 하는 경우
예시와 같이 이벤트를 Props로 전달하여 처리할 수 있습

커스텀 이벤트

const SOS = ({onSOS}) => {
    const [count, setCount] = useState(0); 
    const handleClick = () => {
        if(count >= 2) {
          onSOS();
        }
        setCount(count + 1);
    }
    return (
        <button onClick={handleClick}> 세 번 누르면 긴급호출({count})
        </button>
    ) 
}
const App = () => {
    return (
        <div> 
            <SOS onSOS={() => { alert("긴급사태!");
            }} />
        </div> 
    );
  };

 

단순히 DOM 이벤트를 활용하는 것을 넘어서 나만의 이벤트를 만들 수도 있다.

이벤트 명명법

직접 이벤트를 만들 때에는 이름을 자유롭게 설정할 수 있다.

그러나 보통은 코드를 읽을때 쉽고 빠르게 이해할 수 있도록

“on”+동사또는“on”+명사+동사 형태로 작성합니다.

예시: onClick, onButtonClick, onInputChange 핸들링 함수의 경우 마찬가지로
“handle” + 동사 또는 “handle” + 명사 + 동사 의 형태로 작성하며,

“handle” 대신 이벤트명과 동일한 “on”을 앞에 붙여도 무방

 


참고

 

Event - Web API | MDN

Event 인터페이스는 DOM 내에 위치한 이벤트를 나타냅니다.

developer.mozilla.org

 

반응형

댓글