안녕하세요! 물결웹팟 OB 박채연입니다 😞
리액트는 state를 통해 동적인 UI를 쉽게 관리할 수가 있는데요,
그래서 이번주엔 State를 사용해 Input 다루기, State 구조 선택하기, 컴포넌트 간 State 공유하기, State를 보존하고 초기화하기 부분을 읽고, 리액트 state를 다시 정복해보려 합니다 !-!
오늘은 제 state가 시들시들해서 호다닥 시작해볼게요 ..
📍 State를 사용해 Input 다루기
입력 필드의 값은 일반적으로 컴포넌트의 State로 관리합니다!
이를 통해 사용자가 입력한 값을 실시간으로 추적할 수 있고,
양방향 데이터 바인딩을 구현하지 않더라도 React의 단방향 데이터 흐름을 유지할 수 있습니다.
입력 필드의 value를 컴포넌트 State에 연결하고,
onChange 이벤트 핸들러를 통해 State를 업데이트하죠!
function InputComponent() {
const [inputValue, setInputValue] = React.useState("");
const handleChange = (e) => setInputValue(e.target.value);
return <input value={inputValue} onChange={handleChange} />;
}
다중 필드 입력을 다루는 경우엔,
입력 필드의 name 속성을 활용해 State를 동적으로 업데이트하고,
다중 입력 필드를 단일 State 객체로 관리하면 코드가 간결해집니다 !
function FormComponent() {
const [formData, setFormData] = React.useState({
username: "",
email: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prevData) => ({
...prevData,
[name]: value,
}));
};
return (
<form>
<input
name="username"
value={formData.username}
onChange={handleChange}
placeholder="Username"
/>
<input
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
/>
<p>Preview: {JSON.stringify(formData)}</p>
</form>
);
}
📍 State 구조 선택하기
State의 구조는 코드의 가독성과 유지보수성에 큰 영향을 미치는데요,
리액트에서는 State를 가능한 간단하고 평평하게(flat) 유지하는 것이 좋다고 합니다!
State를 중첩된 객체로 관리하면 불필요한 복잡성이 생길 수 있으니,
필요한 데이터만 State로 관리하고, 계산 가능한 데이터는 State에 포함하지 않습니다.
// 중첩된 구조를 피하는 예시
function UserInfo() {
const [name, setName] = React.useState("");
const [age, setAge] = React.useState(0);
// State를 평평하게 유지해 변경 관리가 용이
return <div>{/* UI 렌더링 */}</div>;
}
하지만 우리는 ,, 중첩된 state를 사용해야 하는 경우도 있죠!
그럴 땐, 불변성을 유지하며 관리할 수 있도록 해야합니다.
State 객체의 중첩된 속성을 업데이트하려면 스프레드 연산자(...)를 사용해 기존 데이터를 복사하는 형태로
불변성을 유지해 리액트의 의 상태 비교 최적화(shallow comparison)가 제대로 작동하도록 해야 합니다.
function UserProfile() {
const [user, setUser] = React.useState({
name: "John Doe",
address: {
city: "New York",
zip: "10001",
},
});
const updateCity = () => {
setUser((prevUser) => ({
...prevUser,
address: {
...prevUser.address,
city: "Los Angeles",
},
}));
};
return (
<div>
<p>{user.name} lives in {user.address.city}.</p>
<button onClick={updateCity}>Move to LA</button>
</div>
);
}
📍 컴포넌트 간 State 공유하기
애플리케이션이 커질수록 컴포넌트 간 State를 공유해야 하는 경우가 생기는데요,
이때, 공통 조상 컴포넌트(Lifting State Up)에 State를 선언하고, 자식 컴포넌트에 Prop으로 전달해 사용합니다.
State를 공유해야 할 컴포넌트들의 가장 가까운 공통 부모 컴포넌트에서 관리하고,
Prop을 통해 데이터를 내려보내며, 데이터 변경 함수를 자식에서 호출합니다.
function Parent() {
const [count, setCount] = React.useState(0);
return (
<div>
<Child count={count} increment={() => setCount(count + 1)} />
</div>
);
}
function Child({ count, increment }) {
return <button onClick={increment}>Count: {count}</button>;
}
📍 State를 보존하고 초기화하기
컴포넌트를 다시 렌더링하거나 초기 상태로 리셋해야 하는 경우를 대비해 State를 보존하거나 초기화하는 패턴을 이해해야 합니다.
useState 초기값을 함수로 전달하면 초기화 비용을 줄일 수 있고,
상태를 완전히 초기화하려면 부모 컴포넌트에서 상태를 재설정하거나, 상태 업데이트 로직을 잘 설계합니다.
function Counter() {
const [count, setCount] = React.useState(() => {
console.log("초기값 계산");
return 0; // 초기값
});
const reset = () => setCount(0);
return <button onClick={reset}>Reset</button>;
}
정리해보자면, state를 관리할 땐
간단하고 명확하게 유지하기
불변성을 지키기 위해 기존 데이터를 복사 후 업데이트하기
컴포넌트 간 State가 필요하다면 공통 부모에서 관리하기
초기값 및 리셋 로직을 설계해 유지보수를 쉽게 만들기
컴포넌트 구조와 상태의 복잡성을 최소화하고,
컴포넌트 간 데이터 흐름을 명확히 관리할 수 있도록 노력하는 게 중요할 것 같아요! ☺️
그럼 마지막으로, 공부하며 든 궁금증 하나 남기겠습니다 !
input 값을 다룰 때마다, input의 value를 console에 찍곤 하잖아요! 그때 무슨 타자를 칠 때마다 console에 값이 우르르르르 변경되는게 보이곤 하는데요, 이걸 보면서 이렇게 state가 자주 바뀌면 성능이 좋진 않겠단 생각이 들곤 했습니다! 그래서 이걸 어떤 식으로 관리해야 좋을지, 또 여러분은 어떤 식으로 관리해왔는지 궁금합니다! 💬
모두모두 솝커톤 끝나고 작업하느라 고생 많으셨습니당 ,, 파이팅!
'나야, 리액트 스터디' 카테고리의 다른 글
[week 6] Ref로 값 참조하기, Ref로 DOM조작하기 (3) | 2024.12.01 |
---|---|
[week6] Ref로 값 참조하기 (3) | 2024.12.01 |
[week5] 컴포넌트 간 state 공유 (4) | 2024.11.25 |
[week5] 선언적 방식, 불필요한 상태 없애기, key를 이용해 state 초기화하기, Props를 state에 미러링X (4) | 2024.11.25 |
[week 5] state를 보존하고 초기화하기 (3) | 2024.11.25 |