From 18050e2a3206a5a897690ec38365650908161f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=B8=ED=83=9C?= Date: Fri, 8 Dec 2023 14:53:03 +0900 Subject: [PATCH] =?UTF-8?q?fix=20:=20=EB=B3=91=ED=95=A9=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/search/page.tsx | 25 +++++++++- src/components/search/Card/RouteCard.tsx | 60 ++++++++++++++---------- src/recoil/search.ts | 23 ++++++++- src/type/search.ts | 11 ++++- 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index 70692b5..8526c8b 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -8,6 +8,7 @@ import { addressesState, pathResultState, remainPathState, + searchState, } from '@/recoil/search'; import Input from '@/components/search/Input'; import ResultCards from '@/components/search/Card/ResultCards'; @@ -23,6 +24,7 @@ export default function SearchPage() { const [inputType, setInputType] = useState('departure'); const resetAddresses = useResetRecoilState(addressesState); const [remainPath, setRemainPath] = useRecoilState(remainPathState); + const [search, setSearch] = useRecoilState(searchState); useEffect(() => { if ( @@ -45,10 +47,24 @@ export default function SearchPage() { } // eslint-disable-next-line react-hooks/exhaustive-deps }, [pathResult.arrival.address, pathResult.departure.address]); + + const changeSearchValue = () => { + setSearch({ arrival: search.departure, departure: search.arrival }); + }; + + const deleteSearchValue = () => { + setSearch({ ...search, departure: '' }); + }; + return (
- {'출발지, + {'출발지, changeSearchValue()} + style={{ cursor: 'pointer' }} + />
setInputType('arrival')} />
- {'출발지 + {'출발지 deleteSearchValue()} + style={{ cursor: 'pointer' }} + />
diff --git a/src/components/search/Card/RouteCard.tsx b/src/components/search/Card/RouteCard.tsx index fecf360..49718d2 100644 --- a/src/components/search/Card/RouteCard.tsx +++ b/src/components/search/Card/RouteCard.tsx @@ -3,40 +3,46 @@ import styled from 'styled-components'; import icX from 'public/assets/icons/ic_x_sm.png'; import Image from 'next/image'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; -import { pathResultState, remainPathState } from '@/recoil/search'; +import { useRecoilState, useSetRecoilState } from 'recoil'; +import { pathResultState, remainPathSelector } from '@/recoil/search'; import { useMounted } from '@/hooks/useMounted'; -import { v4 as uuidv4 } from 'uuid'; +import { IPathPropsWithoutKey } from '@/type/search'; +import { MouseEvent } from 'react'; const RouteCard = () => { const { isMounted } = useMounted(); - const remainPath = useRecoilValue(remainPathState); + const [remainPath, setRemainPath] = useRecoilState(remainPathSelector); const pathResult = useSetRecoilState(pathResultState); + const showResult = ({ arrival, departure }: IPathPropsWithoutKey) => { + pathResult({ + arrival: { + location: arrival.location, + address: arrival.address, + x: arrival.x, + y: arrival.y, + }, + departure: { + location: departure.location, + address: departure.address, + x: departure.x, + y: departure.y, + }, + }); + }; + const removePath = (id: string, e: MouseEvent) => { + e.stopPropagation(); + setRemainPath(remainPath.filter((path) => path.id !== id)); + }; return ( <> {isMounted && - remainPath?.map(({ arrival, departure }) => { - const uniqueKey = uuidv4(); - const showResult = () => { - pathResult({ - arrival: { - location: arrival.location, - address: arrival.address, - x: arrival.x, - y: arrival.y, - }, - departure: { - location: departure.location, - address: departure.address, - x: departure.x, - y: departure.y, - }, - }); - }; - + remainPath?.map(({ id, arrival, departure }) => { return ( - showResult()}> + showResult({ arrival, departure })} + >

@@ -46,7 +52,11 @@ const RouteCard = () => { 도착지 {arrival.location}

- 저장된 경로 삭제 + 저장된 경로 삭제 removePath(id, e)} + />
); diff --git a/src/recoil/search.ts b/src/recoil/search.ts index f3b1efa..3a34c1e 100644 --- a/src/recoil/search.ts +++ b/src/recoil/search.ts @@ -1,7 +1,12 @@ import { IAddressProps, IPathProps } from '@/type/search'; -import { atom } from 'recoil'; +import { DefaultValue, atom, selector, RecoilEnv } from 'recoil'; +import { v4 as uuidv4 } from 'uuid'; import { recoilPersist } from 'recoil-persist'; +//Next.js 개발 환경에서 Recoil을 사용하면 파일이 변경되어 다시 빌드되는 과정에서 atom으로 만든 state가 재선언된다. +//재선언되는 과정에서 이미 key로 선언된 값을 key로 사용해서 문제가 발생하기 때문에 +// 해결하기 위해 Env 추가 +RecoilEnv.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED = false; const { persistAtom } = recoilPersist(); export const searchState = atom({ @@ -39,3 +44,19 @@ export const remainPathState = atom({ default: [], effects_UNSTABLE: [persistAtom], }); + +export const remainPathSelector = selector({ + key: 'remainPathSelector', + get: ({ get }) => { + const remainPath = get(remainPathState); + return remainPath.map((path) => ({ id: uuidv4(), ...path })); + }, + set: ({ set }, newValue) => { + if (!(newValue instanceof DefaultValue)) { + set( + remainPathState, + newValue.map(({ id, ...path }) => path) + ); + } + }, +}); diff --git a/src/type/search.ts b/src/type/search.ts index 0dec334..dca26ef 100644 --- a/src/type/search.ts +++ b/src/type/search.ts @@ -40,7 +40,11 @@ export interface IQueryProps { route: IPathResultProps[]; } -export interface IPlaceCard extends Location { +export interface IPlaceCard { + location: string; + address: string; + x: number; + y: number; type: string; } @@ -61,3 +65,8 @@ export interface IPathProps { arrival: Location; departure: Location; } + +export interface IPathPropsWithoutKey { + departure: Location; + arrival: Location; +}