useState는 상태를 관리해주는 hook이다.
import React, {useState} from 'react';
//useState 예시
const Counter = () =>{
const[value,setValue] = useState(0);
return(
<div>
<p>
{value}
</p>
<button onClick={()=>setValue(value+1)}>+1</button>
<button onClick={()=>setValue(value-1)}>-1</button>
</div>);
};
export default Counter;
set 함수를 사용하면 React는 다음 상태를 저장하고 새 값으로 구성 요소를 다시 렌더링하고 UI를 업데이트 한다.
그러나 set 함수를 호출해도 이미 실행 중인 코드의 현재 상태는 변경 되지 않는다.
function handleClick(){
// 이렇게 setAge를 3번 사용하는 경우 age 값이 실행 중인 코드에서는 변하지 않으므로 결국 age 값은 1만큼 증가한다
setAge(age+1)
setAge(age+1)
setAge(age+1)
}
function handleClick(){
// 상태 대신 업데이터 함수를 전달 하면 이러한 문제를 해결 할 수 있다.
setAge(a => a+1);
setAge(a => a+1);
setAge(a => a+1);
}
React에서 state는 읽기 전용으로 간주되므로 기존 객체를 변경하는 대신 교체해야 한다.
import { useState } from 'react';
export default function Form() {
const [form, setForm] = useState({
firstName: 'Barbara',
lastName: 'Hepworth',
email: 'bhepworth@sculpture.com',
});
return (
<>
<label>
First name:
<input
value={form.firstName}
onChange={e => {
setForm({
...form,
firstName: e.target.value
});
}}
/>
</label>
<label>
Last name:
<input
value={form.lastName}
onChange={e => {
setForm({
...form,
lastName: e.target.value
});
}}
/>
</label>
<label>
Email:
<input
value={form.email}
onChange={e => {
setForm({
...form,
email: e.target.value
});
}}
/>
</label>
<p>
{form.firstName}{' '}
{form.lastName}{' '}
({form.email})
</p>
</>
);
}
import { useState } from 'react';
import AddTodo from './AddTodo.js';
import TaskList from './TaskList.js';
let nextId = 3;
const initialTodos = [
{ id: 0, title: 'Buy milk', done: true },
{ id: 1, title: 'Eat tacos', done: false },
{ id: 2, title: 'Brew tea', done: false },
];
export default function TaskApp() {
const [todos, setTodos] = useState(initialTodos);
function handleAddTodo(title) {
setTodos([
...todos,
{
id: nextId++,
title: title,
done: false
}
]);
}
function handleChangeTodo(nextTodo) {
setTodos(todos.map(t => {
if (t.id === nextTodo.id) {
return nextTodo;
} else {
return t;
}
}));
}
function handleDeleteTodo(todoId) {
setTodos(
todos.filter(t => t.id !== todoId)
);
}
return (
<>
<AddTodo
onAddTodo={handleAddTodo}
/>
<TaskList
todos={todos}
onChangeTodo={handleChangeTodo}
onDeleteTodo={handleDeleteTodo}
/>
</>
);
}
React는 초기 상태를 한번 저장하고 다음 렌더링에서는 무시한다
// 이렇게 사용시 createInitalTodos()는 초기 렌더링에만 사용되지만 여전히 모든 렌더링에서 이 함수를 호출하고 있다. 그렇기에 큰 배열을 만들거나 비용이 많이 드는 계산을 수행하는 경우 낭비일 수 있다.
function TodoList(){
const [todos, setTodos] = useState(createInitalTodos());
}
// 그렇기에 이와 같이 초기화 함수를 전달하여 초기화 중에만 함수를 호출 하도록 한다.
function TodoList(){
const [todos,setTodos] = useState(createInitialTodos);
}
key attribute는 일반적으로 목록을 렌더링할 때 사용된다. 그러나 키는 목록만을 위한 것이 아니다. 키를 사용하여 React가 모든 구성요소를 구별하도록 만들 수 있다. 기본적으로 React는 부모 내의 순서를 사용하여 구성 요소를 식별한다. 그러나 키를 사용하면 이것이 첫 번째 카운터나 두번째 카운터가 아니라 특정 카운터임을 React에 알릴 수 있다.
import { useState } from 'react';
export default function App() {
const [version, setVersion] = useState(0);
function handleReset() {
setVersion(version + 1);
}
return (
<>
<button onClick={handleReset}>Reset</button>
<Form key={version} />
</>
);
}
function Form() {
const [name, setName] = useState('Taylor');
return (
<>
<input
value={name}
onChange={e => setName(e.target.value)}
/>
<p>Hello, {name}.</p>
import { useState } from 'react';
export default function CountLabel({ count }) {
const [prevCount, setPrevCount] = useState(count);
const [trend, setTrend] = useState(null);
if (prevCount !== count) {
setPrevCount(count);
setTrend(count > prevCount ? 'increasing' : 'decreasing');
}
return (
<>
<h1>{count}</h1>
{trend && <p>The count is {trend}</p>}
</>
);
}