React 배우기 - 상태(State)
1. State
상태(State)란 컴포넌트가 가질 수 있는 동적인 데이터를 의미합니다.
- 사용자가 입력한 텍스트
- 현재 선택된 메뉴 항목
- 토글 버튼의 on/off 상태
- 서버에서 받아온 데이터
useState 기본 문법 설명
const [state, setState] = useState(initialValue);
// - state: 현재 상태 값
// - setState: 상태를 변경하는 함수
// - initialValue: 초기 상태 값
- State와 Props의 차이
리액트 컴포넌트는 입력과 출력이 있는데 prop를 통해 입력된 데이터를 우리가 만든 컴포넌트 함수가 처리해서 retrun을 통해 출력한다.
props는 컴포넌트를 사용하는 외부자를 위한 데이터이다.
state는 props와 비슷하지만 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있다.
state는 컴포넌트 자신을 위한 데이터이다.
- State의 특징
- 상태는 객체 형태의 데이터이다.
- 상태는 컴포넌트 내부에서 선언되어야 한다.
- 상태는 props와 달리 컴포넌트 내부에서 값을 변경할 수 있다.
- State를 사용하는 이유
- 사용자와의 상호작용을 통해 동적인 웹 페이지를 만들기 위해서 사용한다.
- 상태가 변경되면 컴포넌트는 다시 렌더링된다.
- State 동작 원리
- 기본 구조
// useState의 반환값
const [state변수, state변경함수] = useState(초기값);
- 동작 원리
// useState는 항상 2개의 요소를 가진 배열을 반환합니다
const array = useState('winter');
// array = ['winter', function()]
// 이것을 풀어서 쓰면
const name = array[0]; // 'winter'
const setName = array[1]; // setState 함수
// 구조 분해 할당으로 한 번에 쓰면
const [name, setName] = useState('winter');
2. State 사용
- 상태를 사용하지 않고 버튼 클릭시 이름 변경
- 상태를 사용하지 않으면 버튼을 클릭해도 이름이 변경되지 않는다.
- console.log()를 통해 name의 값이 변경되는 것을 확인할 수 있다.
// App.js
import React from 'react';
function App() {
let name = 'winter'; // name 변수에 'winter'라는 값을 저장한다.
// changeName() 함수를 정의한다.
function changeName() {
// name의 값이 'winter'이면 'fall'로, 'fall'이면 'winter'로 변경한다.
name = name === 'winter' ? 'fall' : 'winter';
console.log(name); // name의 값을 출력한다.
}
return (
// name의 값을 출력한다.
// 버튼을 클릭하면 changeName() 함수를 실행한다.
<div className='root'>
<h1>{name}</h1>
<button onClick={changeName}>Name Change</button>
</div>
);
}
export default App;
- Vanilla 자바스크립트를 활용한 버튼 클릭시 이름 변경
- 상태를 사용하지 않고 Vanilla js를 활용해 버튼을 클릭시 이름을 변경할 수 있다.
- 하지만 이 방법은 리액트에서 권장하지 않는 방법이다.
// App.js
import React from 'react';
function App() {
let name = 'winter'; // name 변수에 'winter'라는 값을 저장한다.
// changeName() 함수를 정의한다.
function changeName() {
// name의 값이 'winter'이면 'fall'로, 'fall'이면 'winter'로 변경한다.
name = name === 'winter' ? 'fall' : 'winter';
console.log(name); // name의 값을 출력한다.
document.querySelector('h1').innerText = name; // h1 태그의 텍스트를 name의 값으로 변경한다.
}
return (
<div className='root'>
<h1>{name}</h1>
<button onClick={changeName}>Name Change</button>
</div>
);
}
export default App;
- State(상태)를 사용해 버튼 클릭시 이름 변경
- State(상태)를 사용해 버튼을 클릭시 이름을 변경한다.
- State(상태)를 사용하면 컴포넌트가 다시 렌더링된다.
// App.js
// useState를 불러온다.
import React, { useState } from 'react';
function App() {
// name : 상태의 이름, setName : 상태를 변경하는 함수
// useState('winter') : 상태의 초기값
const [name, setName] = useState('winter');
// 배열의 구조 분해 할당
// const name = useState('winter')[0];
// const setName = useState('winter')[1];
// useState('winter') : 상태의 초기값
function changeName() {
// 상태를 변경하는 함수(setName)를 사용해 name의 값을 변경한다.
// name의 값이 'winter'이면 'fall'로, 'fall'이면 'winter'로 변경한다.
// 삼항 연산자 : 조건 ? 참일 때 값 : 거짓일 때 값
setName(name === 'winter' ? 'fall' : 'winter');
}
return (
// button을 클릭하면 changeName() 함수를 등록합니다.
<div className='root'>
<h1>{name}</h1>
<button onClick={changeName}>Name Change</button>
</div>
);
}
export default App;
3. 버튼 클릭시 숫자 변경
- State(상태)를 사용해 버튼을 클릭시 숫자를 변경한다.
- State(상태)를 사용하면 컴포넌트가 다시 렌더링된다.
// App.js
import React, { useState } from 'react'; // useState를 불러온다.
function App() {
const [number, setNumber] = useState(0);
function increase() {
setNumber(number + 1);
}
function decrease() {
setNumber(number - 1);
}
return (
<div className='root'>
<h1>{number}</h1>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
);
}
export default App;
4. 메뉴 토글 버튼
<button
onClick={() => {
setIsOpen(!isOpen);
}}
>
{/* {isOpen ? 'x' : '='} */}
{isOpen ? <IoCloseSharp /> : <FaBars />}
</button>
5. 에어비앤비 선택 메뉴 활성화
'use client';
import React, { useState } from 'react';
import { TbTicket } from 'react-icons/tb'; // 컬쳐 아이콘
import { GiTreehouse } from 'react-icons/gi'; // 한적한 시골
import { MdOutlinePhotoCamera } from 'react-icons/md'; // 최고의 전망
import { BiHome } from 'react-icons/bi'; // 한옥
const Sort = () => {
const sortArr = [
{ value: '컬쳐 아이콘', icon: <TbTicket /> },
{ value: '한적한 시골', icon: <GiTreehouse /> },
{ value: '최고의 전망', icon: <MdOutlinePhotoCamera /> },
{ value: '한옥', icon: <BiHome /> },
];
const [selected, setSelected] = useState(0);
return (
<div className='max-w-6xl mx-auto px-4'>
<div
className='flex justify-between items-center gap-8 border-b'
role='tablist'
aria-label='숙소 카테고리'
>
{sortArr.map((item, index) => (
<button
key={index}
onClick={() => setSelected(index)}
className={`
flex flex-col items-center justify-center
py-4 gap-2 flex-1
transition-all duration-200 ease-in-out
focus:outline-none
${selected === index ? 'text-black border-b-2 border-black' : 'text-gray-500 hover:text-black hover:border-b-2 hover:border-gray-300'}
`}
role='tab'
aria-selected={selected === index}
>
<span
className='text-2xl'
aria-hidden='true'
>
{item.icon}
</span>
<span className='text-xs font-medium whitespace-nowrap'>{item.value}</span>
</button>
))}
</div>
<div className='mt-4'>
{sortArr.map((item, index) => (
<div
key={index}
role='tabpanel'
aria-hidden={selected !== index}
className={`
transition-all duration-200 ease-in-out
${selected === index ? 'block' : 'hidden'}
`}
>
{item.value} 관련 숙소가 표시됩니다.
</div>
))}
</div>
</div>
);
};
export default Sort;
6. Input 상태 관리
- State(상태)를 사용해 input의 상태를 관리한다.
// App.js
import React, { useState } from 'react'; // useState를 불러온다.
function App() {
// 상태를 정의한다. text는 상태의 이름, setText는 상태를 변경하는 함수이다.
// useState('')은 상태의 초기값이다.
const [text, setText] = useState('');
// input의 값을 변경했을 때 실행되는 함수이다.
// e.target.value : input의 value 속성의 값을 가져온다.
function handleChange(e) {
setText(e.target.value); // setText() 함수를 사용해 text의 값을 변경한다.
// text 상태 값이 변경되면 컴포넌트가 다시 렌더링되기 때문에 text 상태 값이 출력된다.
}
return (
// input의 값을 출력한다.
// input의 값이 변경되면 handleChange() 함수를 실행한다.
<div className='root'>
<input
type='text'
value={text}
onChange={handleChange}
/>
<p>{text}</p>
</div>
);
}
export default App;
7. navigation 구현
import { NavLink } from 'react-router-dom';
const Navigation = () => {
// NavLink의 className을 위한 공통 함수
const getLinkStyle = ({ isActive }) => {
return `
transition-colors duration-200
hover:text-yellow-500
${isActive ? 'text-yellow-500' : 'text-white'}
`;
};
return (
<nav>
<ul className='flex space-x-4'>
<li>
<NavLink
to='/'
className={getLinkStyle}
>
Home
</NavLink>
</li>
<li>
<NavLink
to='/about'
className={getLinkStyle}
>
About
</NavLink>
</li>
<li>
<NavLink
to='/contact'
className={getLinkStyle}
>
Contact
</NavLink>
</li>
</ul>
</nav>
);
};
export default Navigation;
'Front > React' 카테고리의 다른 글
React Library (0) | 2023.11.06 |
---|---|
Framer Motion - 리액트 라이브러리, 애니메이션 구현 (0) | 2023.11.04 |
이벤트(Event) - React 배우기 (0) | 2023.10.31 |
속성(Props, Properties) - React 배우기 (0) | 2023.10.29 |
React에서 GSAP 사용하기 (0) | 2023.10.27 |