해당 포스트는 코드아카데미의 React 101 강의의 필기입니다.
클래스 컴포넌트의 단점이 부각되자 함수 컴포넌트에서도 여러가지 동작을 할 수 있도록 Hooks
를 추가함
➡️ state, lifecycle 기능을 함수형 컴포넌트에서도 이용할 수 있도록 해주는 장치
참고 : https://reactjs.org/docs/hooks-reference.html
named export여서 { }
사이에 가져와야함
import React, { useState } from 'react';
react 라이브러리에서 React
와 { useState }
를 가져온다!
useState()
: 리액트 라이브러리에 정의된 자바스크립트 Function
리턴값으로 두개의 값을 담은 배열을 도출함
const [toggle, setToggle] = useState();
식으로 정의해야 두 값에 대한 변수명을 줄 수 있음
현재 렌더링에서 변경되어야하는 값이 있다면 setter 함수를 호출하여 상태 변경을 하면 됨.
상태 변경이 일어나면 자동으로 re-rendering이 됨.
예시 컴포넌트
import React, { useState } from 'react';
export default function ColorPicker() {
const [color, setColor] = useState();
const divStyle = {backgroundColor: color};
return (
<div style={divStyle}>
<p>The color is {color}</p>
<button onClick={() => setColor('Aquamarine')}>
Aquamarine
</button>
<button onClick={() => setColor('BlueViolet')}>
BlueViolet
</button>
<button onClick={() => setColor('Chartreuse')}>
Chartreuse
</button>
<button onClick={() => setColor('CornflowerBlue')}>
CornflowerBlue
</button>
</div>
);
}
State Hook는 모든 원시 자료형과 배열, 객체를 다룰 수 있음
(예. boolean
→ toggle between true / false)
처음 렌더링 시 초기값을 지정하고 싶다면 useState(여기!
)에 넣으면 됨
초기값을 주지 않으면 undefined
로 렌더링 함
개발자간 커뮤니케이션을 위해 초기값을 세팅하지 않겠다는 의사를 표시하고 싶을 경우
null
을 넣자!
Initial color를 보라색으로 설정할 경우
const [color, setColor] = useState('Purple');
JSX요소에 attribute로 준 이벤트리스너에 인라인으로 state setter 함수를 사용해도 좋지만, 따로 더 복잡한 로직을 가진 함수를 만들어 불러오는 것도 좋음.
const handleChange = (event) => {
const newEmail = event.target.value;
setEmail(newEmail);
}
더 짧게는 구조분해할당을 이용할 수 있음
const handleChange = ({ target }) => {
setEmail(target.value);
}
그리고 만든 함수를 jsx요소에 추가한다
return <input type="text" onChange={handleChange} />
콜백함수 형태로 하는 것이 가장 안전하다
const [count, setCount] = useState(0);
const increment = () => setCount(prevCount => prevCount + 1);
// 혹은
setCount(prevCount => prevCount + 1);
// 덜 좋은 예
setCount(count + 1);
static array
그냥 값을 가지고 있고, 변하지 않는 배열의 경우 함수 컴포넌트 밖에 선언함.
변하지 않으니 재렌더링 시 포함될 필요 없음.
dynamic array
변하는 값을 가진 배열의 경우 state로 관리함.
값을 추가하는 경우 push하지 않고, spear syntax를 사용해 이전의 값을 복사한 후 값을 추가 : setState(prev => [newVal, ...prev])
array methods
.includes()
.filter()
.map()
등의 배열을 다루는 메소드를 많이 사용함
예. includes - 참/거짓 값 도출할 경우
filter - 특정 값을 없앨 경우
map - 특정 배열로 비슷한 요소들을 렌더링할 경우
Groceries 리스트에 추가 + 삭제 (index로)
function GroceryCart() {
const [cart, setCart] = useState([]);
const addItem = (item) => {
setCart(prev => [item, ...prev]);
};
const removeItem = (targetIndex) => {
setCart(prev => prev.filter((item, index) => index !== targetIndex));
};
return (
<div>
<h1>Grocery Cart</h1>
<ul>
{cart.map((item, index) => (
<li onClick={() => removeItem(index)} key={index}>
{item}
</li>
))}
</ul>
<h2>Produce</h2>
<ItemList items={produce} onItemClick={addItem} />
<h2>Pantry Items</h2>
<ItemList items={pantryItems} onItemClick={addItem} />
</div>
);
}
export default function Login() {
const [formState, setFormState] = useState({});
const handleChange = ({ target }) => {
const { name, value } = target;
setFormState((prev) => ({
...prev,
[name]: value
}));
};
return (
<form>
<input
value={formState.firstName}
onChange={handleChange}
name="firstName"
type="text"
/>
<input
value={formState.password}
onChange={handleChange}
type="password"
name="password"
/>
</form>
);
}
handleChange()
함수는 event의 target을 argument로 받아 target에서 name값과 value값을 동일명의 변수에 넣음[name]: value
꼴의 새 프로퍼티를 넣음 (spread syntax 사용)💡
<input>
에는 보통 없는name
속성을 추가하여 한 이벤트 핸들러로 두개의 인풋에 대응할 수 있음
💡 한 State에 너무 많은 정보를 넣으면, 이를 업데이트하는 함수를 정의할 때, 너무 복잡해질 수 있음 → 적당히 나누어 여러개의 State 사용
☺️ 이런 글이 필요했는데!! 감사합니다!