위코드 1차 프로젝트 컨버스(Converse) 클론 프로젝트 중 저의 가장 큰 과제였던 인스타그램 기능 구현에 대한 리뷰 글입니다. 💕
인스타 페이지 구조는 아래와 같다.
main
> InstaPage
> InstaList
> InstaBox
, InstaModal
인스타리스트 페이지
인스타박스와 인스타 모달의 상단 컴포넌트로 인스타 페이지의 값을 받아와 모달과 박스에 해당 값을 뿌려준다.
class InstaList extends Component {
constructor(props) {
super(props);
this.state = {
currentModalIdx: null,
modalState: false,
data: [],
};
}
modalStateHandler = (index) => {
const { modalState } = this.state;
this.setState({
modalState: !modalState,
currentModalIdx: index,
});
document.body.style.overflow = "hidden";
};
1) modalState로 불리언 값에 따라 모달창이 띄워지게 세팅, 하단 컴포넌트인 인스타 박스에
modalStateHandler
라는 함수를 props로 전달하여 해당 박스 클릭 시 상단 컴포넌트인 인스타리스트modalState
값이 변경되게 만든다.
2) 동시에 같은 props로currentModalIdx
라는 현재의 인덱스 값을 null로 비워두고 해당 인스타박스 클릭 시 그 인덱스 번호가 채워지게 만든다.
인스타리스트
closeModal = (e) => {
if (e.target.className === "InstaModal") {
this.setState({
modalState: false,
});
}
document.body.style.overflow = "unset";
};
인스타모달
<div className="InstaModal" onClick={this.props.closeModal}>
모달창을 띄웠지만 어떻게 close하는 방법에 대해서도 애를 먹었는데 e.target.className으로 해결!
closeModal
를 인스타 모달창에 props로 전달 해당 배경화면(전체를 감싸는 div)가 InstaModal일 경우 modalState의 값을 다시 false로 변경하여 모달창 close
> 인스타리스트
nextIdxHandler = (index) => {
const { currentModalIdx } = this.state;
this.setState({
currentModalIdx: currentModalIdx + 1,
});
};
backIdxHandler = (index) => {
const { currentModalIdx } = this.state;
this.setState({
currentModalIdx: currentModalIdx - 1,
});
};
> 인스타모달
class InstaModal extends Component {
clickNextHandler = () => {
this.props.nextIdxHandler();
};
clickBackHandler = () => {
this.props.backIdxHandler();
};
render() {
const { user, image, text, user_profile_image } = this.props.data[0];
let changedText = text.split("%").join("\n");
return (
<div className="InstaModal" onClick={this.props.closeModal}>
<button className="backBtn" onClick={this.clickBackHandler}>
<IoIosArrowBack className="btn" />
</button>
모달창의 백버튼을 클릭시
clickBackHandler
가 실행 이것은 상단인 인스타리스트의backIdxHandler
가 실행되어currentModalIdx
의 값이 변경되게 된다
넥스트 버튼도 위와 마찬가지이다 그럼 어떻게 되냐 ?
> 인스타리스트
render() {
const { posts } = this.props;
const { currentModalIdx, modalState } = this.state;
let data = posts.filter((item, index) => index === currentModalIdx);
> 인스타모달
render() {
const { user, image, text, user_profile_image } = this.props.data[0];
인스타 모달창에 전달되는 data는 필터함수로
currentModalIdx
값과 같은 것으로 필터되어 전달 인스타 모달창은 결국 현재의 인덱스에 따라 모든 데이터가 출력되도록 설정 😭😂
요고 생각하기 넘나 어려웠다 ㅠㅠㅠㅠㅠ
const LIMIT = 8;
class InstaPage extends React.Component {
constructor(props) {
super(props);
this.state = {
posts: [],
offset: 0,
loading: false,
};
}
offset은 보여주고자 하는 페이지의 시작점이라 생각하면 된다. loading을 불리언으로 관리해서
true
가 될 시 로딩 로고창이 뜨게 만들었다.LIMIT
은 몇개까지 보여줄 것인에 대한 것으로 변함없는 값으로 상수로 관리한다.
clickViewMore = () => {
const { offset, posts, loading } = this.state;
this.setState(
{
offset: offset + 1,
loading: true,
},
() => {
fetch(`${instaAPI}?page=${this.state.offset}&limit=${LIMIT}`)
.then((res) => res.json())
.then((res) => {
this.setState(
{
posts: [...this.state.posts, ...res.posts],
},
() => {
this.setState({ loading: false });
}
);
});
}
);
};
클릭이 일어났을 때
setState
으로 offset값과 loading값을 변화시켜준다.
콜백함수로 fetch함수를 호출시켜 res에 넣고 그것을spread operator
를 통해 다시 기존의 post의 데이터와 함치는 과정을 거친다. 그리고 다시 loading의 state값을 false로 바꿔 로딩 로고창이 없어지게 만든다.
componentDidMount() {
const { offset } = this.state;
fetch(`${instaAPI}?page=${offset}&limit=${LIMIT}`)
.then((res) => res.json())
.then((res) => {
this.setState({
posts: res.posts,
});
});
}
컴디마로 첫 fetch 호출 시에도 마찬가지로 백과 맞춘 fetch주소를 걸어주고 posts에 해당 데이터를 넣어준다.
render() {
const { posts, loading } = this.state;
return (
<div className="InstaPage">
<div className="instaTitle">
<p>CONVERSE COMMUNITY</p>
</div>
<div className="imgContainer">
<InstaList posts={posts} />
</div>
<div className="viewMoreBox">
<button type="text" onClick={this.clickViewMore}>
더보기
</button>
</div>
<div className={`loadingModal ${loading ? "" : "hidden"}`}>
<img src={gif} alt="preloader gif" />
</div>
;
</div>
);
}
}
export default InstaPage;
인스타그램은 한번 클로닝을 해봤던 것으로 나름 수월할 것을 생각했는데... 기능 하나 하나가 나에게 큰 도전이었다. 그래서 가장 애착이 가는 페이지이자 기능의 모음이다.
나에겐 컨버스 클론 프로젝트라 읽고 인스타 기능 프로젝트라고 쓸정도로 도전의 연속이었지만 그 과정에서 react의 state과 props로 데이터를 이동하는 플로우를 익힐 수 있는 소중한 기회였다.