Script
State 응용(input, button) / 리액트에서의 불변성 본문
1.useState + onclick Event
Button과 이벤트 핸들러 구현하기
import React from "react";
function App() {
// 버튼을 눌렀을 때 하고 싶은 행동
function onClickHandler() {
console.log("hello button");
}
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
위와 같이 버튼을 눌렀을 때 하고 싶은 행동을 함수로 만들 수 있다.
이것의 작동원리에 대해서 살펴보자.
우선, onclickHandler라는 함수를 만들고 onclick={}에 넣어준다.
React에서는 이러한 방식으로 함수와 컴포넌트(button 태그)를 연결시킨다.
우리는 이때 이 함수를 이벤트 핸들러라고 표현한다.
위의 경우 버튼을 눌렀을 때 콘솔에 "hello button"이 출력될 것이다.
state 구현하고 이벤트 핸들러와 연결하기
import React, { useState } from "react";
function App() {
const [name, setName] = useState("길동이");
function onClickHandler() {
setName("누렁이");
}
return (
<div>
{name}
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
우선 state를 하나 만든다. 버튼을 클릭했을 때 이 state 값을 바꿀 것이다.
이벤트 핸들러를 만들어주고 그 안에 setName을 넣어주자.
이제 button에 onclick으로 이벤트핸들러를 연결해 놓았으니 버튼을 클릭하면
state가 길동이에서 누렁이로 바뀔 것이다.
2.useState + onChange Event
Input과 state 구현하기
import React, { useState } from "react";
const App = () => {
const [value, setValue] = useState("");
return (
<div>
<input type="text" />
</div>
);
};
export default App;
1번에서는 버튼을 다루는 법을 배웠고, 이번에는 input을 다루는 방법을 배워보자.
input에서는 위 코드와 같이 보통 사용자가 입력한 값을 state로 관리하는 패턴을 많이 사용한다.
input과 useState를 사용해서 input의 값을 넣을 value라는 state를 생성했다.
이번에는 function keyword 대신 화살표 함수를 사용한 모습이다.
이벤트핸들러를 구현하고 state와 연결하기
import React, { useState } from "react";
const App = () => {
const [value, setValue] = useState("");
const onChangeHandler = (event) => {
const inputValue = event.target.value;
setValue(inputValue);
};
console.log(value) // value가 어떻게 변하는지 한번 콘솔로 확인해보자.
return (
<div>
<input type="text" onChange={onChangeHandler} value={value} />
</div>
);
};
export default App;
우리는 이벤트 핸들러 안에서 자바스크립트의 event 객체를 꺼내 사용할 수 있다.
사용자가 입력한 input의 값은 event.target.value로 꺼내 사용할 수 있다.
마지막으로 state인 value를 input의 속성인 value값에 넣어주면 input과 state가 연결된다.
input의 value 속성- text나 password 태그에서 초기 글자를 미리 입력해둘 수 있다. (초기값 설정 )
event 객체- DOM과 관련된 이벤트가 발생하면 관련 정보는 모두 event 객체에 저장된다.
ex) 마우스 이벤트 - 마우스의 위치정보 포함 등
키보드 이벤트- 누른 키의 키코드 등
위 작업을 요약하면 사용자가 input에 어떤 값을 입력하면, 그 값을 입력할 때마다, 같은 말로 onChange될 때마다
value라는 state에 setValue해서 넣어주는 것이다.
그래서 input이 '안녕하세요' 일때의 value를 콘솔에 찍어보면 다음과 같이 출력된다.

3.불변성
2주차에서 불변객체를 만드는 방법에 대해서 알아본 적이 있다.
원시타입은 불변성을 가지지만 객체타입은 불변성을 가지지 않는다고 살펴보았다.
이번에는 리액트에서 원시데이터가 아닌 데이터의 불변성을 왜 지켜줘야 하는지의 대해서 얘기해 볼것이다.
변수가 메모리에 데이터를 저장하는 방법
let number =1 이라고 선언을 하면, 메모리에는 1이라는 값이 저장된다.
그리고 number라는 변수는 메모리에 있는 1을 참조한다.
이어서 let secondNumber = 1이라고 다른 변수를 선언했다면, secondNumber도 이미 메모리에 생성되어
있는 1이라는 값을 참조한다.
즉, number와 secondNumber는 변수의 이름은 다르지만, 같은 메모리의 값을 바라보고 있는 것이다.
number === secondNumber //true
하지만 원시데이터가 아닌 값(객체,배열,함수)는 이렇지 않다.
let obj_1 = {name:'kim'} , let obj_2 = {name:'kim'} 이라고 했을때 같은 메모리를 가지지 않고
obj_1과 obj_2라는 메모리 공간에 각각 1을 새롭게 저장한다.
데이터를 수정하면 발생하는 일
만약 기존에 1이던 number를 number=2라고 새로운 값을 할당하게 되면 어떻게 될까?
원시 데이터는 불변성이 있다. 즉, 기존 메모리에 저장이 되어 있는 1이라는 값이 변하지 않고, 새로운 메모리
저장공간에 2가 생기고 number라는 값을 새로운 메모리 공간에 저장된 2를 참조하게 되는 것.
따라서 secondNumber는 number의 값이 2가 되었음에도 여전히 1이라는 값을 갖는다.
number와 secondNumber는 각각 다른 메모리 저장공간을 참조하고 있기 때문.
객체는 어떨까?
obj_1.name = 'park'라고 새로운 값을 할당해보자.
객체는 불변성이 없다. 그래서 기존 메모리 저장공간에 있는 {name:'kim'} 이라는 값이 {name:'park'}으로 바뀌어버린다.
요약하자면, 원시데이터는 수정을 했을 때 메모리에 저장된 값 자체는 바꿀 수 없고
아예 새로운 메모리에 새로운 값을 저장한다.
원시데이터가 아닌 데이터는 수정했을 때 기존에 저장되어 있던 메모리 값 자체를 바꾸어 버린다.
리액트에서는 왜 원시데이터가 아닌 데이터의 불변성을 지켜줘야 할까?
리액트에서는 화면을 리렌더링 할지에 대해 결정할 때 state의 변화를 확인한다.
state가 변하면 리렌더링 되는 것이고, state가 변하지 않으면 리렌더링을 하지 않는다.
그때, 리액트 입장에서는 state가 변했는지 안 변했는지 확인하는 방법이 state의 변화 전,후의 메모리 주소를
비교한다. 그래서 만약 리액트에서 원시데이터가 아닌 데이터를 수정할 때 불변성
(즉, 아예 다른 메모리에 저장하게 하는것)을 지켜주지 않고 직접 수정을 가하면,
값은 바뀌겠지만 메모리 주소는 변하지 않는다.
육안상 값은 바뀌었지만 메모리주소가 변하지 않았기에,리액트 입장에서는 변화를 인지하지 못하고 마땅히 일어나야 할
리렌더링이 일어나지 않게 되는 것.
리액트 불변성을 지키는 방법
배열을 setState 할 때 불변성을 지켜주기 위해, 직접 수정을 가하지 않고 전개 연산자를 사용해서
기존의 값을 새로운 메모리에 복사하고, 그 이후에 값을 수정하는 식으로 구현한다.
전개 연산자- 쉽게 말해, 배열안에 있는 값들을 마음대로 사용하기 위해서 배열을 펼치는 것이다.
펼쳐놓으면 그 안에 있는 값들을 입맛에 맞게 사용하는 것.
ex) 배열을 통째로 매개변수에 넘겨줄 때 or
[3,5,1]의 Math.max를 호출 할때
import React, { useState } from "react";
function App() {
const [dogs, setDogs] = useState(["말티즈"]);
function onClickHandler() {
// spread operator(전개 연산자)를 이용해서 dogs를 복사합니다.
// 그리고 나서 항목을 추가한다.
setDogs([...dogs, "시고르자브르종"]);
}
console.log(dogs);
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
'항해99 > 3주차 주특기 기초' 카테고리의 다른 글
| 컴포넌트 스타일링 (0) | 2022.07.25 |
|---|---|
| 반복되는 컴포넌트 처리하기 (0) | 2022.07.25 |
| State (0) | 2022.07.25 |
| 구조분해 할당과 Props / default Props (0) | 2022.07.23 |
| Props.children (0) | 2022.07.23 |