목표
- 상태 끌어올리기와 내려꽂기에 대해 알아본다.
const Id = () => {
const [id, setId] = React.useState("");
return (
<>
<div className="wrapper">
<label htmlFor="id">ID: </label>
<input id="id" />
</div>
</>
);
};
const Pw = () => {
const [pw, setPw] = React.useState("");
return (
<>
<div className="wrapper">
<label htmlFor="pw">PW: </label>
<input type="password" id="pw" />
</div>
</>
);
};
const App = () => {
return (
<>
<Id />
<Pw />
<div className="wrapper">
<button disabled={true}>
Login
</button>
</div>
</>
);
};
🤔 의문
- 현재 로그인 버튼은 disabled 상태인데, 아이디와 패스워드 모두 입력 됐을 때 어떻게 disabled 값을 false로 만들어 버튼을 활성화 시킬 수 있을까?
아이디와 패스워드 입력창에 값이 변경될 때마다 값을 setValue() 해주고 길이를 확인하여 둘 다 길이가 0이 아니면 활성화 해주면 된다.
const Id = () => {
const [id, setId] = React.useState("");
const onChangeId = (event) => {
setId(event.target.value);
};
return (
<>
<div className="wrapper">
<label htmlFor="id">ID: </label>
<input id="id" onChange={onChangeId} />
</div>
</>
);
};
const Pw = () => {
const [pw, setPw] = React.useState("");
const onChangePw = (event) => {
setPw(event.target.value);
};
return (
<>
<div className="wrapper">
<label htmlFor="pw">PW: </label>
<input type="password" id="pw" onChange={onChangePw} />
</div>
</>
);
};
return (
<>
<Id />
<Pw />
<div className="wrapper">
<button disabled={id.length === 0 || pw.length === 0}>
Login
</button>
</div>
</>
);
🤔 의문
- 그렇다면 자식 컴포넌트에 있는 id, pw state 변수를 어떻게 부모 컴포넌트에서 사용할 수 있을까?
여기서는 상태 끌어 올리기(state lifting up)라는 개념을 적용할 수 있다. 자세한 내용은 React 공식 문서에서 확인할 수 있다.
상태 끌어 올리기(state lifting up)
- 하나의 컴포넌트에서 다른 컴포넌트의 state를 필요로 하면, 가장 가까운 공통 조상으로 state를 들어 올려 사용할 수 있다는 개념이다.
const App = () => {
const [id, setId] = React.useState("");
const [pw, setPw] = React.useState("");
const onChangeId = (event) => {
setId(event.target.value);
};
const onChangePw = (event) => {
setPw(event.target.value);
};
return (
<>
<Id onChangeId={onChangeId} />
<Pw onChangePw={onChangePw} />
<div className="wrapper">
<button disabled={id.length === 0 || pw.length === 0}>
Login
</button>
</div>
</>
);
};
const Id = ({ onChangeId }) => {
return (
<>
<div className="wrapper">
<label htmlFor="id">ID: </label>
<input id="id" onChange={onChangeId} />
</div>
</>
);
};
const Pw = ({ onChangePw }) => {
return (
<>
<div className="wrapper">
<label htmlFor="pw">PW: </label>
<input type="password" id="pw" onChange={onChangePw} />
</div>
</>
);
};
const Toggle = () => {
const [on, setOn] = useState(false);
const onToggle = () => {
setOn((prev) => !prev);
}
return (
<>
<Switch on={on} onToggle={onToggle} />
</>
);
};
const Switch = ({on, onToggle}) => {
return (
<div>
<div>The button is {on ? 'on' : 'off'}</div>
<button onClick={onToggle}>Toggle</button>
</div>
);
};
const Switch = ({on, onToggle}) => {
return (
<div>
<SwitchMessage on={on} />
<SwitchButton onToggle={onToggle} />
</div>
)
}
const SwitchMessage = ({ on }) => {
return <div>The button is {on ? 'on' : 'off'}</div>
}
const SwitchButton = ({ onToggle }) => {
return <button onClick={onToggle}>Toggle</button>
}
🤔 의문
- 한 두개의 컴포넌트에서 프로퍼티를 넘겨주는 것은 문제가 없다.
- 하지만, 프로젝트 규모가 커지면서 하위 컴포넌트가 여러 계층이고 각 하위 컴포넌트마다 프로퍼티를 넘겨 준다면 추적하기 어려워지는 등 여러 문제가 발생한다.
- 어떻게 해결해야 할까?
도움이 많이되었습니다:) 감사해요