import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
여기에는 useState를 사용하여 카운트 상태를 유지하는 Counter 구성 요소가 있습니다. handleClick 함수 내에서 count 상태를 빠르게 연속해서 세 번 업데이트합니다.
이제 'Increment' 버튼을 클릭하면 카운트가 3씩 증가할 것으로 예상되지만 실제로는 그렇지 않습니다. 대신 카운트는 1씩만 증가합니다. 이는 React가 상태 업데이트를 일괄 처리하기 때문에 발생하므로 setCount에 대한 세 번의 호출이 모두 단일 일괄 처리로 처리됩니다. setCount에 대한 각 호출은 업데이트된 값이 아니라 count의 이전 값을 기반으로 하므로 카운트는 1씩만 증가합니다.
이를 수정하기 위해 현재 상태 값을 인수로 받는 콜백 함수를 인수로 취하는 함수형 setCount를 사용할 수 있습니다. 그런 다음 이 현재 값을 사용하여 다음 상태 값을 계산할 수 있습니다.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
일괄 처리를 통해 React는 각 업데이트 후 구성 요소를 렌더링하지 않고 한 번에 모든 상태 업데이트를 수행할 수 있습니다. 대신 상태 업데이트를 대기열에 넣은 다음 업데이트된 상태 값으로 구성 요소를 한 번 다시 렌더링합니다. 이렇게 하면 구성 요소를 다시 렌더링해야 하는 횟수가 줄어들어 성능이 크게 향상될 수 있습니다.
또한 DOM을 너무 자주 업데이트하는 잠재적인 문제를 방지하려면 일괄 처리가 필요합니다. DOM 업데이트는 비용이 많이 드는 작업일 수 있으며 여러 업데이트를 빠르게 연속적으로 수행하면 성능 문제와 시각적 결함이 발생할 수 있습니다. 상태 업데이트를 일괄 처리함으로써 React는 DOM 업데이트를 보다 효율적으로 수행하고 시각적 결함의 가능성을 줄일 수 있습니다.
setNumber(n => n + 1)
업데이터 함수를 사용할 수 있습니다.React에서 뮤테이션은 상태 객체에 직접 적용된 변경 사항을 의미합니다. 업데이트된 값으로 새 상태 개체를 만들지 않고 상태 개체를 직접 수정할 때 변형이 발생할 수 있습니다.
React에서 뮤테이션은 예상치 못한 동작을 유발하고 상태의 변화를 추적하기 어렵게 만들 수 있기 때문에 문제가 됩니다. 상태를 직접 변경하면 React가 변경 사항을 감지하지 못할 수 있으며 이로 인해 가상 DOM과 실제 DOM 간에 불일치가 발생할 수 있습니다. 이로 인해 응용 프로그램에서 시각적 결함 또는 기타 예기치 않은 동작이 발생할 수 있습니다.
상태를 읽기 전용으로 취급한다는 것은 상태 객체를 직접 수정해서는 안 된다는 것을 의미합니다. 대신 업데이트된 값으로 새 상태 개체를 만들고 setState 함수를 사용하여 상태를 업데이트해야 합니다.
import React, { useState } from 'react';
function MyComponent() {
const [person, setPerson] = useState({ name: 'John', age: 30 });
function handleBirthday() {
setPerson(prevPerson => ({ ...prevPerson, age: prevPerson.age + 1 }));
}
return (
<div>
<p>Name: {person.name}</p>
<p>Age: {person.age}</p>
<button onClick={handleBirthday}>Have a Birthday</button>
</div>
);
}
이 예에서는 useState 후크를 사용하여 { name: 'John', age: 30 }의 초기 값을 가진 상태 변수 person을 생성합니다. 사용자가 버튼을 클릭하면 업데이트된 값으로 새 상태 객체를 생성하여 person 상태를 업데이트하는 handleBirthday 함수를 호출합니다.
person 개체를 직접 변경하는 대신 확산 연산자(...)를 사용하여 이전 person 개체의 복사본을 만든 다음 age를 업데이트하여 업데이트된 값으로 새 상태 개체를 만듭니다. 새로운 값을 가진 속성. 이전 상태 개체를 인수로 받는 함수(prevPerson)를 사용하여 이 새 상태 개체를 setPerson 함수에 전달합니다.
이렇게 하면 상태가 변경되지 않고 업데이트되고 응용 프로그램에서 예기치 않은 동작을 방지하는 데 도움이 됩니다.
import React, { useState } from 'react';
function MyComponent() {
const [person, setPerson] = useState({ name: 'John', age: 30 });
function handleBirthday() {
person.age += 1;
setPerson(person);
}
return (
<div>
<p>Name: {person.name}</p>
<p>Age: {person.age}</p>
<button onClick={handleBirthday}>Have a Birthday</button>
</div>
);
}
이 예제에서는 person 객체의 age 속성을 직접 수정하여 업데이트한 다음 동일한 객체를 setPerson 함수에 전달합니다. 이는 상태를 읽기 전용으로 처리하지 않으며 애플리케이션에서 예기치 않은 동작을 유발할 수 있습니다.
상태 개체를 직접 수정하면 React가 변경 사항을 감지하지 못할 수 있으며 이로 인해 가상 DOM과 실제 DOM 간에 불일치가 발생할 수 있습니다. 이로 인해 응용 프로그램에서 시각적 결함 또는 기타 예기치 않은 동작이 발생할 수 있습니다.
따라서 항상 상태를 읽기 전용으로 취급하고 기존 상태 개체를 직접 수정하는 대신 업데이트된 값으로 새 상태 개체를 만드는 것이 중요합니다.
const nextPosition = {};
nextPosition.x = e.clientX;
nextPosition.y = e.clientY;
setPosition(nextPosition);
위와 같은 코드는 괜찮습니다.
객체 내에서 [ 및 ] 중괄호를 사용하여 동적 이름을 가진 프로퍼티를 지정할 수도 있습니다. 다음은 동일한 예시이지만 세 개의 다른 이벤트 핸들러 대신 단일 이벤트 핸들러를 사용한 예시입니다:
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
firstName: 'Barbara',
lastName: 'Hepworth',
email: 'bhepworth@sculpture.com'
});
function handleChange(e) {
setPerson({
...person,
[e.target.name]: e.target.value
});
}
return (
<>
<label>
First name:
<input
name="firstName"
value={person.firstName}
onChange={handleChange}
/>
</label>
<label>
Last name:
<input
name="lastName"
value={person.lastName}
onChange={handleChange}
/>
</label>
<label>
Email:
<input
name="email"
value={person.email}
onChange={handleChange}
/>
</label>
<p>
{person.firstName}{' '}
{person.lastName}{' '}
({person.email})
</p>
</>
);
}
import { useState } from 'react';
export default function Form() {
const [person, setPerson] = useState({
name: 'Niki de Saint Phalle',
artwork: {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
}
});
function handleNameChange(e) {
setPerson({
...person,
name: e.target.value
});
}
function handleTitleChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
title: e.target.value
}
});
}
function handleCityChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
city: e.target.value
}
});
}
function handleImageChange(e) {
setPerson({
...person,
artwork: {
...person.artwork,
image: e.target.value
}
});
}
return (
<>
<label>
Name:
<input
value={person.name}
onChange={handleNameChange}
/>
</label>
<label>
Title:
<input
value={person.artwork.title}
onChange={handleTitleChange}
/>
</label>
<label>
City:
<input
value={person.artwork.city}
onChange={handleCityChange}
/>
</label>
<label>
Image:
<input
value={person.artwork.image}
onChange={handleImageChange}
/>
</label>
<p>
<i>{person.artwork.title}</i>
{' by '}
{person.name}
<br />
(located in {person.artwork.city})
</p>
<img
src={person.artwork.image}
alt={person.artwork.title}
/>
</>
);
}
let obj = {
name: 'Niki de Saint Phalle',
artwork: {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
}
};
실제로는 아래처럼 두개의 객체가 있는 것이고, 하나의 객체 안에서 다른 객체를 참조하고 있는 형태입니다.
let obj1 = {
title: 'Blue Nana',
city: 'Hamburg',
image: 'https://i.imgur.com/Sd1AgUOm.jpg',
};
let obj2 = {
name: 'Niki de Saint Phalle',
artwork: obj1
};
{...obj, something: 'newValue'}
를 사용하여 객체 사본을 만들 수 있습니다.