교육/엘리스 SW 학습 내용

[엘리스sw] 10주차 3일 - Props, State, 이벤트 처리

꼽파 2024. 3. 7. 00:06


◆ Props와 State

◆ 이벤트 처리


Props

props란

  • 컴포넌트로 전달되는 매개변수
  • 기본적으로 Component에 원하는 값을 넘겨줄 때 사용하며, 넘겨줄 수 있는 값은 변수, 함수, 객체, 배열 등 JavaScript의 요소라면 제한이 없음.
  • 주로 component의 '재사용'을 위하여 사용함.

 

컴포넌트 생성

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

 

컴포넌트 사용

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

 

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 (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)

  • Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 도와줌.
  • Key는 element에 안정적인 고유성을 부여하기 위해 배열 내부의 Element에 지정해야 함.
  • Key는 배열 안에서 형제 사이에서 고유해야 하고, 전체 범위에서 고유할 필요는 없음.
  • 두 개의 다른 배열을 만들 때 동일한 key를 사용할 수 있음.
const Names = () => {
	const names = [
    	{key: '1', value: '민수'},
        {key: '2', value: '영희'},
    	{key: '3', value: '길동'},
    ]
	return (
    	<div>
        	{names.map((item) => (
            	<li key={item.key}>{item.value}</li>
            ))}
    	</div>
    )
}

State

  • State는 Component 내에서 유동적으로 변할 수 있는 값을 저장한다.
  • 개발자가 의도한 동작에 의해 변할 수도 있고, 사용자의 입력에 따라 새로운 값으로 변경될 수도 있음.
  • State값이 변경되고 재랜더링이 필요한 경우에 React가 자동으로 계산하여 변경된 부분을 렌더링한다.
import { useState } from 'react';

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

 

State 값을 직접 변경하지 마세요.

  • State 값을 직접 변경하게 되면 React가 Component를 다시 렌더링할 타이밍을 알아차리지 못함.
    반드시 setState 함수를 이용해 값을 변경해라.
  • setState 함수를 호출할 때 React에게 "다시 렌더링 해주세요~"라는 명령이 내려진다.
import { useState } from 'react';

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

→ 에러가 나지는 않지만, 화면에서는 증가를 하지 않는다.

 

State를 변경하는 두 가지 방법

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

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

 

2) setState에 함수를 넣기

함수를 넣는 경우 함수가 반환(return)하는 값으로 State가 변경됨.

현재 값을 기반으로 State를 변경하고자 하는 경우 함수를 넣는 방법을 권장함.

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

 

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

  • user object 안의 grade가 변경되었지만 user 자체가 변경되지 않아서 React가 State의 변경을 감지하지 못함.
const [user, setUser] = 
useState({name: "민수", grade: 1})
setUser((current) => {
	current.grade = 2;
    return current;
})
  • 기존 user의 내용을 새로운 object에 담고, grade를 변경한다.
const [user, setUser] = 
useState({name: '민수', grade: 1})
setUser((current) => {
	const newUser = { ...current }
    newUser.grade = 2
    return newUser;
})

이벤트 처리

이벤트란?

  • 이벤트(event) : 웹 브라우저가 알려주는 HTML 요소에 대한 사건의 발생을 의미함.
  • 유저의 행동에 의해 발생할 수도 있으며, 개발자가 의도한 로직에 의해 발생할 수도 있음.
    → 이렇게 발생한 이벤트는 자바스크립트를 이용해 대응할 수 있음.
    ex. Element가 로딩되었을 때, 사용자가 Element를 클릭했을 때, 마우스를 올렸을 때, 더블 클릭했을 때, 키보드 입력을 주었을 때 등 다양한 이벤트가 존재함.
  • 이벤트 핸들러 함수에서는 다양한 로직을 처리하고, 그 결과를 사용자에 출력하여 알릴 수 있음.

 

이벤트 처리(핸들링) 방법

핸들링 함수 선언

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

 

익명 함수로 처리

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

 

이벤트 객체

  • DOM Element의 경우 핸들링 함수에 이벤트 object를 매개변수로 전달한다.
  • 이벤트 object를 이용하여 이벤트 발생 원인, 이벤트가 일어난 Element에 대한 정보를 얻을 수 있다.
  • 이벤트 형태(클릭, 키 입력 등)와 DOM 종류(button, form, input 등)에 따라 전달되는 이벤트 object의 내용이 다르니 유의해야 한다.
const App = () => {
	const handleChange = (event) => {
    	console.log(event.target.value + "라고 입력하셨네요.");
    }
    return (
    	<div>
    		<input onChange={handleChange} />
    	</div>
    );
};

 

많이 쓰이는 DOM 이벤트

  • onClick: Element를 클릭했을 때
  • onChange: Element의 내용이 변경되었을 때 (input의 텍스트를 변경, 파일 선택 등)
  • onKeyDown, onKeyUp, onKeyPress: 키보드 입력이 일어났을 때
  • onDoubleClick: Element를 더블 클릭했을 때
  • onFocus: Element에 Focus 되었을 때
  • onBlur: Element가 Focus를 잃었을 때
  • onSubmit: Form Element에서 Submit 했을 때

컴포넌트 내 이벤트 처리

DOM 버튼 클릭

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

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

DOM Input 값을 State에 저장하기

const App = () => {
	const [inputValue, setInputValue] = useState("defaultValue");
    
    const handleChange = (event) => {
    	setInputValue(event.target.value);
    }
    
    return (
    	<div>
        	<input onChange={handleChange}
            defaultValue={inputValue} />
        </div>
        <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={handleCahnge} value={user.school} />
        <p>
        	{user.name}님은 {user.school}에 재학중입니다.
        </p>
        </div>
    );
};
  • State를 여러 개 선언할 수도 있지만 object를 활용하여 여러 개의 input을 state로 관리하는 방법도 있다.
  • target으로부터 name을 받아와 해당 name의 key에 해당하는 value를 변경하여 state에 반영한다.

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

 

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

  • 사용자가 입력한 정보를 현재 컴포넌트가 아닌 부모 컴포넌트에서 활용해야 하는 경우 예시와 같이 이벤트를 Props로 전달하여 처리할 수 있음.
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>
    )
}

 

커스텀 이벤트

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>
    );
};

세 번 연속 눌렀을 때 가능하도록 함.

 

이벤트 명명법

  • 직접 이벤트를 만들 때에는 이름을 자유롭게 설정할 수 있다.
  • 그러나 보통은 코드를 읽을 때 쉽고 빠르게 이해할 수 있도록 "on" + 동사 또는 "on" + 명사 + 동사 형태로 작성한다.
  • 예시) onClick, onButtonClick, onInputChange 핸들링 함수의 경우
  • 마찬가지로 "handle" + 동사 또는 "handle" + 명사 + 동사 의 형태로 작성하며, "handle" 대신 이벤트명과 동일한 "on"을 앞에 붙여도 무방하다.
const App = () => {
	const handleClick = () => {
    	alert("클릭했습니다.);
    }
    return (
    	<div>
        	<button onClick={handleClick}>클릭하세요</button>
        </div>
    );
};
728x90