요즘 부트캠프의 바쁜 일정 덕분에 새로운 지식들을 빠르게 습득하고 있다는 기분이 들지만, 한편으론 개인 프로젝트를 진행할 시간이 점점 부족해져서 그런지 한편으론 아쉽다. 그래도 나름 시간을 내서 틈틈히 개인프로젝트를 진행중이며, 최근엔 기존의 회원가입 및 로그인 관련 로직들을 리팩토링하는 작업을 진행했었다.
현재 진행중인 사이드 프로젝트의 전체적인 구조는 API 요청 및 상태관리 로직등 을 관리하는 container 컴포넌트와 presenter 컴포넌트를 분리시킨 'Container + Presenter Patternd' 디자인 패턴을 기반으로 작업중이며, 아직 해당 디자인 패턴에 대한 이해는 부족하지만, 지인의 피드백을 받아가며, 컴포넌트를 효과적으로 분리하려고 노력중이다.
또한 기존에는 API 요청같은 비동기 처리에만 redux-saga를 사용하고, 컴포넌트간의 데이터 흐름은 위와 같이 hook의 setState를 이용해서 handler라는 set 함수를 props로 내려주고, 이를 모아서 Container에서 dispatch 했지만, 이번 기회에 컴포넌트 간의 데이터 흐름도 redux-saga를 이용해서 제어하도록 변경하였다.
CHANGE_FIELD
는 register, login영역 데이터 흐름의 핵심적인 기능을 담당하고 있는 액션이다. 우선 해당 리듀서에 회원가입 시 필요한 모든 데이터들을 initialState에 담아놓은 뒤, CHANGE_FIELD를 발생시키는 changeField 함수를 만들어줬다.
onChange 함수는 데이터 흐름과 관련된 로직이기에 container에 선언해줬으며, 입력받을 데이터의 이름인 (name)과 값(value)를 인자로 받은 뒤 changeField를 디스패치 해준다.
name, email, password, residence 등 데이터 흐름이 필요한 하위 컴포넌트들로 내려주었다.
// { ...import modules, styled components }
const Password = ({ onChange, confilmErr }) => {
const onChangeHandler = (event) => {
// 해당 폼의 name과 value를 onChange로 전달한다.
const { name, value } = event.target; // 구조 분해 할당
onChange(name, value);
}; //
let conditonErrMessage = <ErrMsg>패스워드가 서로 일치하지 않습니다.</ErrMsg>; // 조건부 렌더링
const scrollTo = () => { // 스크롤 조정
scroller.scrollTo('myScrollToElement', {
duration: 800,
smooth: 'easeInOutQuart',
offset: -200,
});
};
useEffect(() => {
if (confilmErr) {
console.log('error!');
scrollTo();
}
}, [confilmErr]);
const { password, confilmPassword } = useSelector((registerReduce) => ({
password: registerReduce.password,
confilmPassword: registerReduce.confilmPassword,
})); // input에 초기값이 필요하므로 useSelector로 리덕스 스토어의 password와, confilmPassword를 받아온 뒤 각 input에 value로 지정해준다.
return (
<div>
<RegisterInputText>패스워드</RegisterInputText>
<RegisterInput
name="password"
type="password"
value={password} // useSelector로 가져온 값
onChange={onChangeHandler} //변화가 생길때마다 onChangeHandler에 의해 디스패치된다.
style={{ width: '170px' }}
required
/>
<RegisterInputText>패스워드 확인</RegisterInputText>
<Element name="myScrollToElement"></Element>
<RegisterInput
name="passwordConfirm"
type="password"
value={confilmPassword} // useSelector로 가져온 값
onChange={onChangeHandler}
style={{ width: '170px' }}
required
/>
{confilmErr ? conditonErrMessage : null}
</div>
);
};
export default Password;
각 항목의 컴포넌트를 전부 올릴 순 없으므로 패스워드 컴포넌트를 예시로 들어보려한다.
input에 변화가 생길때마다 onChangeHandler 함수가 실행되면서 state에 입력값이 정상적으로 들어간다.
container에서 useSelector로 각 하위 컴포넌트의 데이터들을 참조하고 있기때문에, 최종적으로 사용자가 모든 정보 입력을 마친뒤 submit을 하면 container에서 이를 모아서 회원가입 액션으로 넘기게된다.