[뉴스모아 #3] 뉴스 검색 추가 및 리스트 페이지 완료

CMK·2024년 1월 22일
0

NewsMoa

목록 보기
3/4

recoil 사용

페이지 렌더링시 매번 뉴스 데이터를 새로 받아 오는게 느리기도 하고 하루 api 요청 횟수가 정해져 있어서
뉴스 데이터를 다른 페이지를 갔다 와도 데이터를 유지하여 api호출을 줄이고, props drilling도 줄이기 위해 전역 상태 관리 라이브러리인 recoil을 사용하기로 했다
props drilling의 depth가 2이상이거나 setState를 넘겨줘야 할때 사용했다


이미지 404 오류

이전에 403 Forbidden 오류를

<img referrerPolicy="no-referrer" src="" alt="" />

위와 같은 referrerPolicy를 추가하여 해결 했었는데 추가로 404오류가 발생하였다
404 에러는 서버에 요청한 데이터가 없을 경우 뜨는것이였다
해당 이미지 url을 직접 확인해보니 역시나 존재하지 않았고 아마도 api측에서 이미지 url을 잘못 저장하여 생기는 오류인것 같았다
해당 오류를 해결하기 위하여 onError 속성을 사용하였다

<img referrerPolicy="no-referrer" src="" alt="" onError={(error)=>(event.currentTarget.src = "/logoWhite.svg")} />

앞으로 어떤 상황이 생길지 모르니 onError 사용을 습관화 해야겠다


헤더 반응형 햄버거 메뉴 추가 및 스크롤 문제

해상도의 width가 1024px 이하일 경우에는 햄버거 메뉴가 나타나도록 하였다
헴버거 메뉴를 antdMaterial-UI 같은 라이브러리 쓰려다가 처음부터 해당 라이브러리를 사용하여 UI구축을 하였으면 몰라도 햄버거 메뉴 하나만을 위해 사용하는건 별로일꺼 같다라는 생각이 들어 직접 간단하게라도 구현하기로 하였다

미디어쿼리를 사용해 max-width: 1024px 이하일 경우에 헤더에 있던 서치바를 제거하고 햄버거 메뉴가 나타나게 구현하였다

그러던중 스크롤시 배경이 스크롤 되는 문제가 발생하였다

해당 문제를 해결하기 위해 햄버거 메뉴가 열려있는 동안에는 body의 overflow를 "hidden"으로 변경 하여 해결하였다

 useEffect(() => {
    // 배경 스크롤 방지
    if (isHamburger) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "auto";
    }
  }, [isHamburger]);

뉴스 검색 추가

뉴스 검색을 추가하면서 뉴스 데이터 저장을 수정 했다

기존

  setTranslateData((prev) => {
    // 새로운 데이터를 추가할 새로운 객체 생성
    const newData = { ...prev };

    // result 배열을 순회하면서 데이터를 적절한 국가 키에 추가
    result.forEach((el) => {
      const country = el[0].country;

      // 해당 국가 키가 이미 newData에 존재하는지 확인
      newData[country] = newData[country]
        ? [...newData[country], ...el] // 이미 존재한다면 새로운 데이터를 기존 배열에 추가
        : el; // 존재하지 않는다면 새로운 배열을 만들어 추가
    });

    return newData;
  });

수정

  const updateData = (setData, result, isSearch) => {
    setData((prev) => {
      const newData = { ...prev };

      result.forEach((el) => {
        // isSearch가 true이면 국가 코드 + search를 키로 사용하고,
        // false이면 국가 코드(el[0].country)를 키로 사용
        const key = isSearch ? el[0].country + search : el[0].country;

        //해당 키가 이미 newData에 존재하는지 확인 및 있으면 데이터 추가 없으면 만들기
        newData[key] = newData[key] ? [...newData[key], ...el] : el;
      });

      return newData;
    });
  };

  // path에 따라서 데이터 저장위치 변경
  if (path === "search") {
    updateData(setSearchData, result, true);
  } else {
    const setData = path === "rending" ? setRendingData : setListData;
    updateData(setData, result, false);
  }

이렇게 path에 따라서 각각 다른 recoilState에 저장되도록 하였다

뉴스 검색은 useEffect를 활용하여 search state에 값이 입력되면 실행 되게 하였다

  useEffect(() => {
    if (listData[selectCountry] === undefined && !isSearch) {
      // 렌더링 및 선택 국가 뉴스 데이터가 없을 경우 요청
      getData("list", [countriesData[selectCountry]], 10, 1);
      return;
    }

    if (searchData[selectCountry + search] === undefined && isSearch) {
      // 검색시 뉴스 데이터가 없을 경우 요청
      getData("search", [countriesData[selectCountry]], 10, 1, search);
      return;
    }
  }, [selectCountry, search]);

또한, onChange로 search state를 변경하면 연속해서 api가 요청되기 때문에 엔터키를 입력시 데이터가 변경되게 하였다

  const onInputKeyPress = (event) => {
    const value = inputRef.current.value;
    // 입력키가 엔터키가 아니거나 검색어가 이전 검색어와 같을경우 return
    if (event.key !== "Enter" || value?.trim() === search) return;

    if (value === "") {
      // 검색어가 있는 상황에서 검색어를 지울경우 isSearch 변경하여 최근뉴스로 변경
      setIsSearch(false);
      setSearch(value);
      return;
    }
    if (value !== undefined && value?.trim() !== "") {
      // isSearch 변경하여 뉴스검색으로 변경
      setIsSearch(true);
      setSearch(value);
      return;
    }
  };

리스트 페이지 완료

0개의 댓글