컴포넌트에서 보여줘야 하는 내용이 사용자 인터랙션에 따라 바뀌어야 할 때 어떻게 구현해야 하는지 알아보겠다.
리액트 16.8 이전 버전에서는 함수형 컴포넌트에서는 상태를 관리할 수 없었는데 리액트 16.8 에서 Hooks 라는 기능이 도입되면서 함수형 컴포넌트에서도 상태를 관리할 수 있게 되었다.
❗ useState
useState 함수는 리액트의 Hooks 중 하나다.
const [현재 상태값, 상태값 갱신함수] = useState(상태 초기값);
원래는 밑에 코드 같이 써야하지만 ES6의 destructuring(구조 분해 문법)를 이용하여 각 원소를 추출하여 위에 코드처럼 사용하는 것이다.
const numberState = useState(0); const number = numberState[0]; const setNumber = numberState[1];
<app.js>
import React from 'react'; import Counter from './components/counter'; export default function App() { return ( <Counter /> ); }
<counter.js>
import React from 'react'; export default function Counter() { return ( <div> <h1>0</h1> <button>+1</button> <button>-1</button> </div> ); }
다음은 +1버튼을 클릭하면 숫자가 증가하고 -1버튼을 클릭하면 숫자가 감소했다는 문구를 콘솔창에 띄워보는 함수를 생성한 것이다.
<counter.js>import React from 'react'; export defualt function Counter() { const onIncrease = () => { console.log('1이 증가되었습니다.') } const onDecrease = () => { console.log('1이 감소하였습니다.'); } return ( <div> <h1>0</h1> <button onClick={onIncrease}>+1</button> <button onClick={onDecrease}>-1</button> </div> ); }
컴포넌트에서 동적인 값을 상태(state)라고 한다. 리액트에 useState 라는 함수가 있는데 이것을 사용하면 컴포넌트에서 상태를 관리 할 수 있다.
<counter.js>import React, { useState } from 'react'; function Counter() { const [number, setNumber] = useState(0); const onIncrease = () => { setNumber(number + 1); } const onDecrease = () => { setNumber(number - 1); } return ( <div> // 이제 h1에서는 0이 아니라 {number}를 보여주어야 한다. <h1>{number}</h1> <button onClick={onIncrease}>+1</button> <button onClick={onDecrease}>-1</button> </div> ); }
📕 useState( )로 여러개의 상태값 관리하기
- ☝🏻 input 태그가 하나일 경우
<userList.js>import React, { useState } from 'react'; export default function User () { const [text, setText] = useState(''); const onChange = (e) => { setText(e.target.value); // 이벤트가 일어나는 타겟의 value를 text값으로 업데이트 한다. }; const onReset = () => { setText(''); // text 값을 공백으로 업데이트 한다. }; return ( <div> <!-- onChange 이벤트 등록 value값에 text 상태값 주기 --> <input onChange={onChange} value={text} /> <button onClick={onReset}>초기화</button> <div> <b>내용: {text}</b> </div> </div> ); }
- ✌🏻 input 태그가 여러개인 경우
동일한 태그가 여러개일 경우 useState, onChange를 여러개 만들지 말고 각 태그에 name값을 설정해주고 이벤트가 발생했을 때 상태값을 관리하는 것이 좋다.import React, { useState } from "react"; export default function User() { // 여러개의 state를 관리해야 하기 때문에 useState함수는 // 객체 형태여야 한다. const [inputs, setInputs] = useState({ name: "", nickname: "" // 초기값 설정 }); // 두 name 속성값을 추출 const { name, nickname } = inputs; const onChange = (e) => { // 이벤트 타겟 속성 value, name 추출 const { value, name } = e.target; setInputs({ ...inputs,[name]: value, }); }; const onReset = () => { setInputs({ name: "", nickname: "", }); }; return ( <div> <input name="name" placeholder="이름" onChange={onChange} value={name} /> <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname} /> <button onClick={onReset}>초기화</button> <div> <b>소개 : </b> {name} ({nickname}) </div> </div> ); }
리액트에서 객체를 수정할 때에는 다음 코드처럼 직접 수정하면 안된다!
inputs[name] = value
spread문법을 사용하여 기존 객체를 복사해 새로운 객체를 만들어 거기서 상태를 업데이트 해주어야 한다.
👉🏻 참고링크