기업협업 중이다.. 여전히
Home을 맡았는데, 홈 자체가 네이버 지도를 불러와서
각각 Marker 를 클릭하면 그 Marker(가게) 의 정보가 담긴 캐러셀이 나오게 해야했다!
처음에 했을때는, Marker를 누르면 해당 정보들은 모두 나오는데, 캐러셀 형태로 나오지않았어서 애를 먹었다...
일단 코드를 보면서 정리를 해 보겠다.
아직 데이터가 완성되지 않아서 Mock data 를 이용했다.
📌 여기가 부모컴포넌트인 Home
const Home = () => {
const [homeMartList, setHomeMartList] = useState([]);
const [selectedMart, setSelectedMart] = useState(null);
const handleMarkerClick = (e, mart) => {
setSelectedMart(mart);
};
//MockData시작
useEffect(() => {
fetch('./data/MhomeData.json')
.then(response => response.json())
.then(data => {
setHomeMartList(data.martList);
});
}, []);
const navermaps = useNavermaps();
const HOME_PATH = window.HOME_PATH || '.';
const geocoder = navermaps.Service.geocode(
{
address: '테헤란로 427',
},
function (status, response) {
if (status !== navermaps.Service.Status.OK) {
return alert('Something wrong!');
}
const result = response.result;
const items = result.items;
}
);
if (homeMartList.length === 0) return;
return (
<S.MapBox>
//네이버맵 불러온것
>
{homeMartList.map(mart => {
return (
<Marker
position={new navermaps.LatLng(mart.y, mart.x)}
key={mart.id}
title={mart.name}
icon={{
content: `<S.MarkerBox>
<S.MarkerOrder>${mart.name}</S.MarkerOrder>
${mart.phoneNumber}</S.MarkerBox>`,
}}
onClick={e => handleMarkerClick(e, mart)}
/>
);
})}
//여기가 HomeCarousel을 불러오는 부분!
<HomeCarousel
homeMartList={homeMartList}
selectedMart={selectedMart}
handleModal={handleModal}
/>
</NaverMap>
</S.MapBox>
);
};
export default Home;
//여기가 HomeCarousel을 불러오는 부분!
<HomeCarousel
homeMartList={homeMartList}
selectedMart={selectedMart}
handleModal={handleModal}
/>
- homeMartList : mock데이터를 map을 돌려 setHomeMartList가 상태변화된 것
-selectedMart : Marker을 onClick 했을 때 발생되어 setSelectedMart 의 상태변화 된 것
모두 props로 넘겨준다
📌 자식 컴포넌트 HomeCarousel
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
const HomeCarousel = ({ homeMartList, selectedMart, handleModal }) => {
const settings = {
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
centerMode: true,
centerPadding: '25px',
dot: false,
};
const [slider, setSlider] = useState(null);
//처음 화면이 랜더링 되었을때는 null 이라 캐러셀이 보이지 않음
const smIndex = homeMartList.indexOf(selectedMart);
const selectedMartList = selectedMart ? homeMartList : [];
useEffect(() => {
if (slider) {
slider.slickGoTo(smIndex);
}
}, [smIndex]);
return (
<S.CarouselWholeContainer>
<Slider {...settings} ref={setSlider}>
{selectedMartList &&
selectedMartList.map(mart => (
<S.MartBox key={mart.id} onClick={handleModal}>
캐러셀 안에 content 작성
</S.MartBox>
))}
</Slider>
</S.CarouselWholeContainer>
);
};
export default HomeCarousel;
📍 정리해보겠댜
<Slider {...settings} ref={setSlider}>
- <Slider> 컴포넌트는 react-slick 패키지에서 이미지나 콘텐츠 등을 슬라이드 형태로 제공하는 컴포넌트 이다.
- {...settings} 슬라이드 보여줄 때 사용할 설정 값으로, slick 에서 제공해주고 원하는대로 설정할 수 있다!
나는 dot과 옆에 슬라이드 넘어가는 버튼이 필요없어서 저렇게 했다 !
ref = {setSlider}
여기서 setSlider 는 useState 훅을 사용했다.
const [slider, setSlider] = useState(null);
//처음 화면이 랜더링 되었을때는 null 이라 캐러셀이 보이지 않음
slider 변수는 <Slider> 컴포넌트의 ref 속성으로 할당되어서 , slider 변수를 사용하여 <Slider> 컴포넌트 메서드를 호출 할 수 있게 했다.
const smIndex = homeMartList.indexOf(selectedMart);
const selectedMartList = selectedMart ? homeMartList : [];
useEffect(() => {
if (slider) {
slider.slickGoTo(smIndex);
}
}, [smIndex]);
const smIndex = homeMartList.indexOf(selectedMart);
smIndex 는 props로 가져온 homeMartList 배열에서 선택된 마트 객체(selectedMart) 가 위치한 index 를 찾는 함수로 로직을 짜 보았다.
const selectedMartList = selectedMart ? homeMartList : [ ] ;
삼항 연산자를 사용하여, selectedMartList 변수는 선택된 마트가 있으면 homeMartList 배열을 할당하고, 없는경우는 빈 배열을 할당한다는 로직이다.
useEffect(() => {
if (slider) {
slider.slickGoTo(smIndex);
}
}, [smIndex]);
useEffect를 통해 smIndex 값이 변경될 때마다 useEffect가 실행이되고,
이 useEffect 함수 내부에서는 slider 객체가 존재하면
slider.slickGoTo( smIndex ) 매서드를 호출해서 선택된 마트가 첫 번째 슬라이드에 위치하도록 설정했다.
이때, slider 객체는 <Slider> 컴포넌트의 ref 속성을 사용해서 참조한 것이다.
즉, smIndex 값이 변경되서 컴포넌트가 다시 랜더링 될 때마다 실행되고,
slider 객체가 존재할 경우 slickGoTo () 를 실행시켜 슬라이드를 이동시킨다.
그래서 이 함수 덕에 마트가 선택되면 smIndex 값이 변경되어서 해당 마트가 첫 번째 슬라이드에 위치하도록 슬라이드를 이동 시키게 된다 !!!!
진짜 짱어렵네...
slickGoTo가 있는지 처음에 몰랐어서 많이 헤맸다....
동기의 도움으로 해결했다만.. 공식문서 읽는 습관을 좀 가져야 할텐데...
- indexof ( ) 매서드 : 문자열의 위치를 확인하기 위해 씀
이 때, indexOf() 메서드는 대소문자를 구분하고, 일치하는 문자열이 없으면 -1을 반환하니 참고하도록 하자 !!
'프론트앤드 > [React]' 카테고리의 다른 글
[React] useState로 onClick 시 아이콘 변경 + 캐러셀 움직일때 같이 해당 아이콘 변경 (naverMap) (0) | 2023.04.03 |
---|---|
[React] 네이버 지도 API 이용 캐러셀 + center 움직이기 (0) | 2023.03.31 |
[React] Footer 이미지 누를때마다 상태변화 (useState) (0) | 2023.03.28 |
[React] 로그인 구현 + 비밀번호 보이게 기능 코드정리 (0) | 2023.03.27 |
[React] 네이버 지도 API 이용 주소->좌표 구하기 (0) | 2023.03.22 |