항상 두 개 이상의 state 변수를 동시에 업데이트하는 경우 단일 state변수로 병합하는 것이 좋다
const [x, setX] = useState(0);
const [y, setY] = useState(0);
같이 업데이트 하는 경우 이러한 형태보다는
const [position, setPosition] = useState({ x: 0, y: 0 });
이러한 형태가 낫다
여러 state가 모순되고 동의하지 않는 방식으로 state가 구조화 되면 실수할 여지가 생긴다.
import { useState } from 'react';
export default function FeedbackForm() {
const [text, setText] = useState('');
const [isSending, setIsSending] = useState(false);
const [isSent, setIsSent] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
setIsSending(true);
await sendMessage(text);
setIsSending(false);
setIsSent(true);
}
if (isSent) {
return <h1>Thanks for feedback!</h1>
}
return (
<form onSubmit={handleSubmit}>
<p>How was your stay at The Prancing Pony?</p>
<textarea
disabled={isSending}
value={text}
onChange={e => setText(e.target.value)}
/>
<br />
<button
disabled={isSending}
type="submit"
>
Send
</button>
{isSending && <p>Sending...</p>}
</form>
);
}
// Pretend to send a message.
function sendMessage(text) {
return new Promise(resolve => {
setTimeout(resolve, 2000);
});
}
이렇게 하는 경우 isSending과 isSent가 동시에 true가 되는 모순적인 상황이 발생할 가능성이 있다.
그렇기에
import { useState } from 'react';
export default function FeedbackForm() {
const [text, setText] = useState('');
const [status, setStatus] = useState('typing');
async function handleSubmit(e) {
e.preventDefault();
setStatus('sending');
await sendMessage(text);
setStatus('sent');
}
const isSending = status === 'sending';
const isSent = status === 'sent';
if (isSent) {
return <h1>Thanks for feedback!</h1>
}
return (
<form onSubmit={handleSubmit}>
<p>How was your stay at The Prancing Pony?</p>
<textarea
disabled={isSending}
value={text}
onChange={e => setText(e.target.value)}
/>
<br />
<button
disabled={isSending}
type="submit"
>
Send
</button>
{isSending && <p>Sending...</p>}
</form>
);
}
// Pretend to send a message.
function sendMessage(text) {
return new Promise(resolve => {
setTimeout(resolve, 2000);
});
}
isSending과 isSent가 동시에 있어서는 안되므로 typing, sending, sent 중 하나의 state를 취할수 있는 상태 변수로 바꾸는 것이 좋다
렌더링 중 component의 props 또는 기존 state변수에서 일부 정보를 계산할 수 있는 경우 해당 정보를 해당 component의 state에 입력하면 안된다.
import { useState } from 'react';
export default function Form() {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [fullName, setFullName] = useState('');
function handleFirstNameChange(e) {
setFirstName(e.target.value);
setFullName(e.target.value + ' ' + lastName);
}
function handleLastNameChange(e) {
setLastName(e.target.value);
setFullName(firstName + ' ' + e.target.value);
}
return (
<>
<h2>Let’s check you in</h2>
<label>
First name:{' '}
<input
value={firstName}
onChange={handleFirstNameChange}
/>
</label>
<label>
Last name:{' '}
<input
value={lastName}
onChange={handleLastNameChange}
/>
</label>
<p>
Your ticket will be issued to: <b>{fullName}</b>
</p>
</>
);
}
위의 경우 fullName은 firstName과 lastName을 통해 렌더링 중에 항상 계산할 수 있으므로 state에서 제거해야 한다.
동일한 데이터가 여러 state간에 또는 중첩된 객체내에 중복되면 동기화를 유지하기 어렵다.
상태가 너무 중첩되어 쉽게 업데이트할 수 없는 경우 평평하게 만드는 것이 좋다.