인스타그램의 메뉴바를 클론 코딩했습니다
완성된 js 파일은 게시물 하단에서 확인하세요
아래 파일을 통해 구현한 메뉴바의 모습입니다
JSX 부분
<nav className="nav">
// 검색창 왼쪽 로고 부분
<div className="navLeft">
<Link className="logo">
westagram
</Link>
</div>
// 검색창 부분
<div className="searchWrapper">
<input
className="searchBar"
type="search"
value={keyword}
placeholder="검색"
onChange={onChange}
/>
<ul className="searchedLists">
// keyword를 입력하지 않으면 검색결과가 나오는 창이 보이지 않도록 했습니다
{keyword.length > 0 && (
<>
{filteredList.map(profile => (
<li className="searchedList" key={profile.id}>
<img
className="searchedImg"
alt="Profile Img"
src={profile.profileImg}
/>
<span className="searchedId">{profile.profileId}</span>
</li>
))}
</>
)}
</ul>
</div>
// 검색창 오른쪽 아이콘 부분
<div className="navRight">
<img
className="navImg"
alt="Explore Img"
src="이미지 주소"
/>
<img
className="navImg"
alt="Heart Img"
src="이미지 주소"
/>
<img
className="navImg"
alt="Profile Img"
src="이미지 주소"
/>
</div>
</nav>
js 문법 부분
const [profiles, setProfiles] = useState([]);
const [keyword, setKeyword] = useState('');
// mock data이기 때문에 fetch로 불러왔습니다
useEffect(() => {
fetch('/data/profileData.json')
.then(response => response.json())
.then(json => setProfiles(json));
});
// keyword 변화 감지하는 함수
const onChange = e => {
setKeyword(e.target.value);
};
// keyword 입력 시 mockdata와 비교하여 일치하는 리스트 보여주는 함수
const filteredList = profiles.filter(profile =>
profile.profileId.toLowerCase().includes(keyword.toLowerCase())
);
CSS 부분
nav.scss
@import './mixin.scss'
.searchWrapper {
// 기본 position이 relative이기 때문에 이 위치에 따라 아래의 absolute들이 배치됩니다
@include flex(center, center);
flex-direction: column;
.searchBar {
// search bar와 를 absolute로 지정해줘야 페이지의 크기와 관계없이 일정한 position을 유지할 수 있씁니다
position: absolute;
top: 36%;
width: 30%;
height: 30px;
padding: 2px 10px 2px 35px;
border: 1px solid lightgray;
border-radius: 5px;
background: url('이미지 주소') center
no-repeat;
background-position: 10px center;
color: gray;
text-align: left;
}
.searchBar:focus {
outline: none;
}
.searchedLists {
// searchedList를 absolute로 지정해줘야 검색결과를 보여주는 곳의 위치를 검색창 위치에 맞게 조정할 수 있습니다
@include flex(left, null);
position: absolute;
top: 65%;
flex-direction: column;
width: 30%;
height: auto;
border-radius: 5px;
background-color: white;
border: 1px solid lightgray;
border-top: none;
.searchedList {
@include flex(left, center);
padding: 7px 10px 7px 10px;
.searchedId {
padding-left: 10px;
font-size: 14px;
font-weight: bold;
white-space: no-wrap;
}
}
}
}
// 저는 mixin.scss 파일을 따로 분리해서 만들었습니다
mixin.scss
@mixin flex($justify, $align) {
display: flex;
justify-content: $justify;
align-items: $align;
}
Data 부분(mock data)
profileData.js
// 이 형태로 여러 개의 객체를 만들었습니다
[
{
"id": 1,
"profileId": "아이디",
"profileImg": "이미지 주소",
"follower": null,
"time": null,
"following": true
}
]
최종 js 파일
import { useEffect, useState } from 'react';
import { MENU_DATA } from '../Data/MenuData';
import './Nav.scss';
function Nav() {
const [profiles, setProfiles] = useState([]);
const [keyword, setKeyword] = useState('');
useEffect(() => {
fetch('/data/profileData.json')
.then(response => response.json())
.then(json => setProfiles(json));
});
const onChange = e => {
setKeyword(e.target.value);
};
const filteredList = profiles.filter(profile =>
profile.profileId.toLowerCase().includes(keyword.toLowerCase())
);
return (
<nav className="nav">
<div className="navLeft">
<img
className="logoImg"
alt="Insta Logo"
src="이미지 주소"
/>
<span className="fontBold">|</span>
<Link className="logo" to="/login">
westagram
</Link>
</div>
<div className="searchWrapper">
<input
className="searchBar"
type="search"
value={keyword}
placeholder="검색"
onChange={onChange}
/>
<ul className="searchedLists">
{keyword.length > 0 ? (
<>
{filteredList.map(profile => (
<li className="searchedList" key={profile.id}>
<img
className="searchedImg"
alt="Profile Img"
src={profile.profileImg}
/>
<span className="searchedId">{profile.profileId}</span>
</li>
))}
</>
) : null}
</ul>
</div>
<div className="navRight">
<img
className="navImg"
alt="Explore Img"
src="이미지 주소"
/>
<img
className="navImg"
alt="Heart Img"
src="이미지 주소"
/>
</div>
</nav>
);
}
export { Nav };
'Learning Log > React' 카테고리의 다른 글
[react] 드롭다운 메뉴 만들기 (0) | 2023.02.15 |
---|---|
[react] fetch와 async-await (0) | 2023.02.09 |
[react] 클릭 시 보여주는 메뉴 구현하기 + 상수데이터 사용법 (0) | 2023.02.04 |
[react] 댓글 기능 구현하기 (0) | 2023.01.26 |
[react] react 기초 개념 (0) | 2023.01.16 |