07.13 React event handling_정리노트
이제 본격적으로 저번 3장에서 잠시 온클릭으로 맛본거대로 여기 4장에 있는 이벤트 핸들링 정리하겠음!
http://www.yes24.com/Product/Goods/62597469
event
사용자가 웹 브라우저에서 DOM 요소와 상호 작용 하는 것.
클릭을 했을 때는 onclick 이벤트, 마우스 커서를 올렸을 때는 onmouseover, html form 요소에서 값이 바뀔 때 onchange 이벤트 등등이 해당!
이렇게 우리가 html 에서 이벤트를 적용시킬때는 이벤트="" 의 형식으로 "" 안에다가 실행코드를 넣었다. 리액트는 비슷하면서 살짝 다른데,
src/Say
차이점을 정리하자면,
이벤트 이름은 카멜 표기법으로 작성
JSX 문법처럼 이벤트를 적을 때도 역시 카멜표기법을 사용한다. 여기서는 onclick 을 onClick 으로 적은 것처럼!
이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달해야한다.
저번 3장에서도 이렇게 따로 함수를 선언해주고 넘겨주는게 왜 그런거지 의문이었는데, 역시 4장에 나오는군.
리액트에서는 이벤트에 바로 실행코드를 넘겨주는 것이 아니라 함수형태의 객체를 전달해야한다. 함수는 바로 만들어서 적용해도 되고, 렌더링 외부에 미리 만들어서 전달해도 된다.
DOM 요소에만 이벤트를 설정할 수 있다.
이게 머선 말이냐면, html button, input,form,div 등등에 이벤트를 적용시킬 수는 있지만, 우리가 만든 컴포넌트에서 자체적으로는 이벤트를 설정하지 못한다는 말!
이렇게 전달할 수 없다는 의미 ㅇㅇ 이렇게 적으면 우리가 부모 컴포넌트에서 props 의 속성값을 설정해주는거랑 형태가 똑같지!! 그렇다보니 리액트에서는 당연히 이벤트로 보지 않고 그저 onClick 이라는 props 의 설정값으로 인식해버린다!
<div onClick={this.props.onClick}>
{/*JSX 문법안에 주석은 이렇게 적음. 지금은 안에 뭐가 들어간다의 예시용 주석*/}
</div>
하지만 이렇게 전달받은 props를 컴포넌트 내부에서 이벤트로 설정할 수 있다!
리액트에서 지원하는 이벤트
https://reactjs.org/docs/events.html
여기에 지원하는 전체 이벤트가 있으니 참고!
자... 이제 개념을 정리했지만 당연히 나는 다 이해 못했기 때문에 책에 있는 예제를 따라하면서 쳐보자 ! ^ㅠ^
src/EventPractice.js (새로 생성)
컴포넌트를 만들고 위에서 함수형태의 값을 전달해주라 했으니까, return 전에 함수를 하나 생성해주었응
이렇게 이벤트를 적용시켜준다. onChange 즉, 인풋 안에 값이 바뀌면 위에 내가 적어준 onChangeUsername 함수가 실행되도록 하는 것임!! type 이랑 name, placeholer 는 그냥 우리가 html input 적어주는거랑 동일~!~!
src/App
맥북은 역시 대단해 ㅎ 창만 캡쳐가 깐지나게 되는군.
오늘은 EventPractice 를 App에서 불러와주고, 내부 state 값만 바꿔볼거라서 경로는 더이상 적지 않을거라 그동안 123장까지 다한 코드와함께 App 컴포넌트를 전부 캡쳐해봤음!!
위에 코드는 내가 버리기 싫어서 그냥 해놓은거고 지금까지 계속 src 폴더 안에서만 작업했으며, App 이 부모 컴포넌트니까 여기서 전부 내가 지금까지 연습한 컴포넌트들을 불러와서 적어주었음!! 오늘의 내용은 EventPractice 만 적어도 상관없다! 자 이제 그럼 경로 정리는 끝!
쨋든 위에처럼 저렇게 input 을 작성하고 브라우저로 들어가면,
그러면 이런 인풋창이 나타나겠지
인풋창에 마구 타자를 치게 되면, 바뀌는 횟수만큼 이렇게 SyntheticEvent 가 뜰땐테 얘는 웹 브라우저에서 네이티브 이벤트를 감싸는 객체, 즉 이벤트 자체를 가리킴! onChange 이벤트가 딱하고 잘 잡히넹
네이티브 이벤트를 리액트에서 SyntheticEvent 로 감싸는 건데 순수 자바스크립트에서 이벤트를 다룰 때와 인터페이스가 똑같음!!
하지만 SyntheticEvent는 네이티브 이벤트랑 달리 이벤트가 끝나고 나면 이벤트가 초기화 되므로, 정보를 참조할 수는 없다. 그래서 이벤트가 일어나는 객체를 참조할 때는 이렇게 적어주자!!
그러면 우리가 인풋창에 칠 때마다 값이 바뀌니까 이 함수가 발동이 될 것이고, 보면 value 값이 잘담긴다!!!
그러면 이를 이용해서 해당 input 값에 담긴 값을 state 로 담아보자!!
이렇게 useState 를 사용해주고, 맨처음 값은 빈값으로 설정해줬다. 그리고 e.target.value 를 이번에는 console.log 로 찍는게 아니라 세터함수에다가 담아주었다.
그리고 쨋든 우리가 state에 잘 담겼는지 확인을 해주기 위해 버튼도 하나 생성해주었음.
이렇게!! 그리고 버튼을 클릭하면 이벤트를 역시 발생시킬거기 때문에, onClick 이벤트를 실행시킬 onClick 함수를 위에 적어줄 것임.
이렇게!
헷갈릴까봐 전체화면 캡쳐.
여기까지 정리하면, username이라는 state 를 만들어주고, 우리는 이벤트가 발생하면, setUsername 로 state 값을 변환 시켜줄 건데,
초기 username 은 빈칸이지만, input 에서 onChange로 해당 지금 내가 입력한 값이 e.target.value 로 담기게 된다.
그리고 버튼을 클릭하면, onClick 이벤트로 우리가 적어준 onClick 함수가 발동이 되는 것이고, 해당 함수는 바뀐 username 을 얼럿창으로 출력하고, 다시 인풋안은 빈칸으로 초기화 시켜주는 것임!
헥헥.. 복잡하지만 한번 쳐보고 나처럼 혼자 어떤 식으로 굴러가는지 생각해보면 정리가 될 듯하다!
인풋창에 내용을 적고 확인 버튼을 눌렀을 때 해당 값이 얼럿창에 잘 출력되고, 인풋창이 빈 값으로 바뀌면 대성공!
좋아좋아 그러면 인풋에 내용을 입력하고, 엔터를 눌렀을 때도, 똑같은 효과가 나타나게 해보겠음!
onKeyPress 함수를 생성해주고, e.key 가 엔터면, 우리가 만들어준,
요 onClick 함수가 작동하도록 하면 되겠지.
그러고 우리가 원하는 인풋에다가 onKeyPress 이벤트가 발생할 때, 우리가 만든 함수를 {} 로 감싸서 넣어준다.
마찬가지로 엔터를 눌렀을 때도 똑같이 얼럿창이 출력되고, 확인을 눌렀을 때 인풋까지 빈값이 되면 정말 성공!!
근데 만약 우리가 인풋창이 여러개라면, 계속 e.target.value를 가져오는 함수를 여러개 만들어서 각자 인풋에 각자 함수를 적어줘야할까??
인풋창이 2~3개면 상관이 없는데, 여러 개라면? 또 하나의 form 요소로 묶인 인풋에서 값을 가져오려면??
e.target.name 으로 가져오면 된다! 여기서 name 은 우리가 input 에 적었던 name 으로 , 해당 name 을 이용해서 설정
무슨 느낌인지 감이 안오니까 또 같이 치기 ㄲ
이번에는 message 라는 인풋을 만들고, 총 2개를 같이 활용해보겠움.
name과 value 또한 작성해준다. value 에 들어가는 값은 state 값임!
이렇게 두 개의 state 를 선언하지 않고, form 이라는 하나의 state로 묶어주고, 형태는 객체로 해주면 된다!
이제 함수를 작성해봅씨다.
먼저 비구조화 할당으로 객체의 값들을 바로 추출해서 할당해주고,
그런 다음, 기존 비어있던 객체를 복사해서, 우리가 이벤트로 받아온 값들을 객체의 key:value 로 가져와서 덮어씌운다.
{
'username" : input value
'message' : input value
}
이렇게 말이다. 여기에서 정리가 여러가지 필요한데, 하나는 ...form 부분이다.
state 에서 배열이나 객체의 값을 업데이트 할 때는 배열이나 객체의 사본을 만들고, 사본에 값을 업데이트 한 후, 그 사본의 상태를 세터 함수를 통해 업데이트 해야한다.
이 때 쓰이는 연산자가 바로 spread 연산자라 불리는 ... 을 통해 처리한다.
그러니 우리는 객체를 업데이트 해야하므로 ...form 을 통해 객체의 사본을 만들고, 값을 업데이트하게 될텐데,
객체안에서 key 값을 [ ] 대괄호로 감싸게 되면, 그 안에 넣은 레퍼런스가 가리키는 실제의 값이 key값으로 사용된다.
이렇게 하면 내가 맨 위 주석처리로 작성해준 함수 2개를 쓰지 않아도 되는 것!
인풋이 여러개로 늘어나면 늘어날수록 유용하겠다.
근데, 혼자 name 에 대한 부분이 감이 잘 안잡혀서 혼자 이렇게 찍어봄 ㅎ
오옹 이렇게 onChange 이벤트가 동작됨과 동시에 각 인풋의 name 을 받아오는군 음음 잘알겠다!!
ㅎ 모를땐 찍어보는게 장땡
자 정리해서 마지막 실행을 해봅시다!
mport React, { useState } from "react";
const EventPratice = () => {
const [form, setForm] = useState({
username: "",
message: "",
});
const { username, message } = form; // 비구조화할당으로 객체의 값을 바로 추출해서 할당.
console.log(form);
const onChange = (e) => {
const nextForm = {
...form, // 기존 form 내용 복사
[e.target.name]: e.target.value, //원하는 값을 key:value 로 덮어씌우기
};
setForm(nextForm); // 세터함수로 값 업데이트
};
const onClick = () => {
alert(username + ":" + message);
setForm({
username: "",
message: "",
});
};
const onKeyPress = (e) => {
if (e.key === "Enter") {
onClick();
}
};
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="username"
placeholder="이름"
onChange={onChange}
/>
<input
type="text"
name="message"
placeholder="메세지를 입력하세요."
onChange={onChange}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPratice;
최종 코드
이렇게 적고 확인 버튼을 누르거나, message 인풋창에서 엔터를 누르면,
이렇게 value 값이 잘 담기며 출력된다!
오늘은 비록 또 새벽이긴하나...ㅎ 책보면서 따라치면서 이해하는데 어려움은 분명히 있었지만, 혼자 하나하나 쳐보며 다 이해하면서 따라한 것 같아서..? ㅎ (착각인가) 하루만에 수월하게 포스팅을 마무리하게 되어 기쁘다! 마냥 답답하고 무서워했던 리액트가 기초라서 그런지 모르지만 차근차근 극복중! 그러면 오늘의 포스팅은 여기서 마무리!
'React' 카테고리의 다른 글
2021.07.19 React Component 반복 (1) | 2021.07.19 |
---|---|
2021.07.16 React ref (0) | 2021.07.16 |
2021.07.11 React props,state (4) | 2021.07.12 |
2021.07.06 React ? (0) | 2021.07.06 |
2021.05.07 drf & react 연동하기 (16) | 2021.05.07 |
댓글