-
[React] 네이버 지도 API 이용 + Slick 캐러셀 띄우기프론트앤드/[React] 2023. 3. 31. 14:06728x90
기업협업 중이다.. 여전히
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을 반환하니 참고하도록 하자 !!
728x90'프론트앤드 > [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