바닐라 자바스크립트로 구현한 인스타그램 로그인과 메인페이지를
react
로 구현하도록 하겠습니다.
우선
document.querySelect
,addEventListener
와 같은 것을 바꿔야한다.
React에서는 사용하지 않으니 해당 요소를 가져올 땐 useRef()
를 사용하도록 하겠다.
는 아니었다..
준식멘토님이 너무 급하게 하지 말라고 하셔서 조금은 천천히 해볼 생각이다... 어렵구나react
ref
는 최대한 사용하지 않는 것으로!!
input에 아이디와 비밀번호를 쳤는데 왠 걸 setState() 값이 바로 반영 안되고 다음 값이 입력되어서 들어오는 것..
setState()함수는 비동기적으로 동작한다. 즉. setState()
함수를 사용해서 state
를 업데이트해도 즉시 반영되지 않는다는 것이었다.
임시해결법
setTimeout
을 사용해서 의도적으로 리렌더링이 되도록 하는 것 (성능에 문제가 생길 것 같다. 좋은 해결법을 찾아보도록하자) handleChange = ( e ) => {
this.setState({
[e.target.name]: e.target.value
});
setTimeout(this.loginBtnEnable,100)
}
바닐라 자바스크립트로 구현할 땐 js를 이용해서 dom객체에 직접 접근
tag class
명을 바꿔주고 그에 따른 효과를 주었는데 react에서는 생각했던 것처럼 안되서 어려웠다.
예를 들어 로그인 화면에서 위와 같이 자연스럽게 사진이 바뀌는 효과를 준 것을 바닐라자바스크립트로 구현할 때는 아래의 코드같이 login.html
에서 img
상위 부모인 img-slide
자식 요소를 배열로 받아와서 setinterval()
함수를 사용해서 cnt
변수로 각각의 현재 img
요소와 이전 img
요소 객체에 클래스명을 추가하거나 삭제하는 것으로 효과를 냈었다.
<article class="img-slide">
<img src="/img/loginImg1.png" class="img-slide-list" alt="image">
<img src="/img/loginImg2.png" class="img-slide-list" alt="image">
<img src="/img/loginImg3.png" class="img-slide-list" alt="image">
<img src="/img/loginImg4.png" class="img-slide-list" alt="imgae">
</article>
const imgSlide = document.querySelector('.img-slide').children;
let imgArr = [];
let cnt = 4;
function opacityImg() {
if (cnt % 4 === 0) {
imgArr[( imgArr.length - 1 )].classList.remove('img-slide-in');
imgArr[( imgArr.length - 1 )].classList.add('img-slide-out');
imgArr[( cnt % 4 )].classList.remove('img-slide-out');
imgArr[( cnt % 4 )].classList.add('img-slide-in');
} else {
imgArr[( cnt % 4 ) - 1].classList.remove('img-slide-in');
imgArr[( cnt % 4 ) - 1].classList.add('img-slide-out');
imgArr[( cnt % 4 )].classList.remove('img-slide-out');
imgArr[( cnt % 4 )].classList.add('img-slide-in');
}
cnt++;
}
function init() {
for (let i = 0; i < imgSlide.length; i++) {
imgArr.push(imgSlide[i]);
}
if (imgArr)
imgArr[( imgArr.length - 1 )].classList.add('img-slide-in');
setInterval(opacityImg, 2000);
}
init()
"리액트에선 어떻게 해야할까??"
리액트의 장점인 state 관리를 이용하면 된다!! 해당하는 값이 바뀌면 자동으로 Rerendering 되기 때문에 그 장점을 활용하면 되겠다!!
사실 이 개념 자체를 이해하질 못해서 자꾸 바닐라자바스크립트처럼
ref
를 활용해서 그 객체에 접근하려고 삽질을 했었다.. 깨우침을 주신 👍🏻멘토 준식님👍🏻 감사합니다!!😊
state = {
imgNameList : [loginImg1, loginImg2, loginImg3, loginImg4],
loginId : '',
loginIdInput : false,
loginPw : '',
loginPwInput : false,
loginBtnCheck: false,
imgSlideIndex: 4,
};
componentDidMount() {
setInterval(this.opacityImg, 2000);
}
opacityImg = () => {
this.setState({
imgSlideIndex: this.state.imgSlideIndex + 1
});
};
render () {
const { imgNameList, loginBtnCheck, loginIdInput, loginPwInput, imgSlideIndex } = this.state;
return {
... 생략
<article className="img-slide">
<img src={imgNameList[0]} className={( imgSlideIndex % 4 ) === 0 ? 'img-slide-list img-slide-in' : 'img-slide-list img-slide-out'} alt="loginImage"/>
<img src={imgNameList[1]} className={( imgSlideIndex % 4 ) === 1 ? 'img-slide-list img-slide-in' : 'img-slide-list img-slide-out'} alt="loginImage"/>
<img src={imgNameList[2]} className={( imgSlideIndex % 4 ) === 2 ? 'img-slide-list img-slide-in' : 'img-slide-list img-slide-out'} alt="loginImage"/>
<img src={imgNameList[3]} className={( imgSlideIndex % 4 ) === 3 ? 'img-slide-list img-slide-in' : 'img-slide-list img-slide-out'} alt="loginImage"/>
</article>
}
}
위와 같이 state
를 활용해서 +1씩 돌아가면서 해당하는 index일때 클래스 이름을 바꿔주면 된다!!!
리액트 신세계!!!👍🏻👍🏻