query-string : URL 쿼리 파라미터로 카테고리와 정렬 처리

728x90
반응형

🎃쿼리스트링이란?

1. url 경로 (pathname) 다음에 나오는 ? 기호로 시작하는 문자열

2. key=value형태로 여러 개는 & 기호로 매개변수 명시 가능

 

⭐쿼리 스트링 사용 목적 

1) 조건에 맞게 정렬된 형태로 정보 주고 받기 가능

2) 해당 Url로 공유 가능

 

URLSearchParams 객체 사용 이유

1. 쿼리 문자열 파싱 : 현재 페이지 URL의 쿼리 문자열 파싱에 사용 가능

2. 쿼리 문자열 생성 및 수정 : 카테고리 + 정렬 2가지를 사용하기 위해

   새로운 문자열 생성 가능

3. 해당 객체는 'toString()'메소드를 통해 쉽게 문자열로 변환 가능

 

 

🚫구현하는데 시간이 오래 걸린 포인트

쿼리 스트링을 통해 라우팅이 된다는 점에

"Router.tsx'파일을 수정해야한다는 생각에 빠져있었음

=> Link 또는 navigate에 쿼리스트링이 포함된 주소를 전달하기만 하면 됨!

(URL에 추가 정보를 더하는 것 뿐, 라우터 컴포넌트에 설정할 내용이 없음)

 

 

🖥️구현 코드(1)

export type Category = 'knowHow' | 'recommendation' | 'sharing' | 'habit' | 'noCategory' | 'total';
export type SortList = 'popularity' | 'latest';

function ViewAllBody() {
	const [category, setCategory] = useRecoilState<Category>(categoryListState);
	const [sortBy, setSortBy] = useState<SortList>('latest');
	const [searchParams, setSearchParams] = useSearchParams();
	const navigate = useNavigate();
 
	const updateSortOption = (newCategory: Category, newSortBy: SortList) => {
    		setCategory(newCategory);
    		setSortBy(newSortBy);

		const newSearchParams = new URLSearchParams();
		newSearchParams.set('category', newCategory);
    		newSearchParams.set('sort', newSortBy);
    		setSearchParams(newSearchParams);

    		navigate(`/viewAll/?${newSearchParams.toString()}`);
	};
return (
	<St.Button onClick={() => updateSortOption('total', sortBy)} selected={category === 'total'}>
		전체보기
	</St.Button>
	<St.Button onClick={() => updateSortOption('knowHow', sortBy)} selected={category === 'knowHow'}>
		 노하우 공유
	</St.Button>
)

 

1. URLSearchParams();

new 키워드로 인스턴스 생성

set(key, value) : 지정된 키 값 설정

     (이미 있으면 업데이트 / 없으면 새로운 값 추가)

navigate새 URL로 이동시키는 데 사용

 

 

 

URLSearchParams - Web API | MDN

URLSearchParams 인터페이스는 URL의 쿼리 문자열을 대상으로 작업할 수 있는 유틸리티 메서드를 정의합니다.

developer.mozilla.org

 

🖥️구현 코드(2)

function ViewAllBody() {
  const [category, setCategory] = useRecoilState<Category>(categoryListState);
  const [sortBy, setSortBy] = useState<SortList>('latest');
  const [searchParams, setSearchParams] = useSearchParams();
  const validCategories: Category[] = ['knowHow', 'recommendation', 'sharing', 'habit', 'noCategory', 'total'];
  const validSortOptions: SortList[] = ['popularity', 'latest'];
  const navigate = useNavigate();

  useEffect(() => {
    // URL 쿼리 파라미터에서 category와 sort 값을 가져옵니다.
    const urlCategory = searchParams.get('category');
    const urlSortBy = searchParams.get('sort');

    //카테고리 : 전체보기~기타
    if (urlCategory && validCategories.includes(urlCategory as Category)) {
      setCategory(urlCategory as Category);
    } else {
      setCategory('total');
    }

    //정렬 : 인기순 /최신순
    if (urlSortBy && validSortOptions.includes(urlSortBy as SortList)) {
      setSortBy(urlSortBy as SortList);
    } else {
      setSortBy('latest');
    }
  }, [searchParams]);

2. url로 이동하고 다른 브라우저에서 검색해도

동일한 화면 나오도록 하는 포인트 => useEffect 사용!

searchParams.get : 각각의 값 가져오기 

useEffect

: 컴포넌트 마운트 + searchParams 변경될 때 실행

: validCategories & validSortOptions : 유효한 카테고리와 정렬 옵션을 정의

: 기본값으로는 'total'과 'latest'로 설정

 

🖥️구현 코드(2): 개선

 

function ViewAllBody() {
  const [category, setCategory] = useRecoilState<Category>(categoryListState);
  const [sortBy, setSortBy] = useState<SortList>('latest');
  const [searchParams, setSearchParams] = useSearchParams();
  const validCategories: Category[] = ['knowHow', 'recommendation', 'sharing', 'habit', 'noCategory', 'total'];
  const validSortOptions: SortList[] = ['popularity', 'latest'];
  const navigate = useNavigate();

  const updateStateFromUrl = () => {
    // URL 쿼리 파라미터에서 category와 sort 값을 가져옵니다.
    const urlCategory = searchParams.get('category');
    const urlSortBy = searchParams.get('sort');

    //카테고리 : 전체보기~기타
    if (urlCategory && validCategories.includes(urlCategory as Category)) {
      setCategory(urlCategory as Category);
    } else {
      setCategory('total');
    }

    //정렬 : 인기순 /최신순
    if (urlSortBy && validSortOptions.includes(urlSortBy as SortList)) {
      setSortBy(urlSortBy as SortList);
    } else {
      setSortBy('latest');
    }
  };

  //URL에서 상태 읽어오는 useEffect
  useEffect(() => {
    updateStateFromUrl();
  }, [searchParams]);

  //쿼리스트링 : 카테고리+정렬
  const updateSortOption = (newCategory: Category, newSortBy: SortList) => {
    setCategory(newCategory);
    setSortBy(newSortBy);

    const newSearchParams = new URLSearchParams();
    newSearchParams.set('category', newCategory);
    newSearchParams.set('sort', newSortBy);
    setSearchParams(newSearchParams);

    navigate(`/viewAll/?${newSearchParams.toString()}`);
  };

  //초기 마운트 실행시
  useEffect(() => {
    if (searchParams.get('category') === null || searchParams.get('sort') === null) {
      updateSortOption(category, sortBy);
    }
  }, []);

 

 useEffect 2개 사용

1) URL에서 상태 읽어오는 useEffect

- 카테고리 & 정렬값이 변경될때마다 반영하기 위함

 

2) 초기 마운트 실행 사용되는 useEffect

- 컴포넌트 마운트되면 초기 설정값으로 url에 표시하기 위함

 

 

 

 

 

끝.

반응형