I.O + HttpRequest)검색 단어 보존과 무한 스크롤 에러 핸들링

김명성·2022년 7월 23일
0

Error 1. input에 값을 입력하여 HttpRequest를 보낸 뒤 input의 값을 변경하게 되면 이후 스크롤에는 변경된 InputValue로 HttpRequest가 진행될 때.

Solution - 다른 state에 inputValue를 저장하고 스크롤이 진행될 때 보내는 Http Request에는 다른 곳에서 저장한 state 사용하기.

PreventChangeWord라는 state를 따로 만들어 Submit할 때 보내는 Http Request에 inputValue를 저장한다.

const submitHandler = async(e:FormEvent<HTMLFormElement>) => {
  e.preventDefault()
  setIsLoading(true)
  // inputvalue를 다른 state에 저장
  setPreventChangeWord(inputValue)
  setPageNumber(1);
  try{
    
    const responseData = await axios.get(`${API_KEY}&desc_kor=${inputValue}&pageNo=1&numOfRows=10&bgn_year=2017&type=json`)
    if(!responseData.data.body.items){
      setFood([])
      setTotalCount(0)
      setLastData('찾으시는 정보가 없습니다.')
      throw Error('찾으시는 정보가 없습니다.')
    }else{
      
      setLastData('')
      setTotalCount(responseData.data.body.totalCount)
      setFood(responseData.data.body.items);
    }
    
  }catch(err){
    console.error(err)
  }finally{
    setIsLoading(false)
    setIsSearched(true);
  }  
}

이후 Intersection Observer가 실행되면서 보내는 Http Request의 URL을 보면, inputValue를 그대로 사용하는게 아닌, submitHandler에서 저장한 state의 값을 사용하고 있다.
이러면 검색어의 기준이 Submit이 진행될 때의 inputValue가 기준이 되기 때문에 검색 중간에 input의 값이 바뀌더라도 기존의 값으로 계속 Http Request를 보낼 수 있다.

const fetchData = async(pageNumber:number) => {
  setIsLoading(true)

  try{
    
    const responseData = await axios.get(` ${API_KEY}&desc_kor=${preventChangeWord}&pageNo=${pageNumber}&numOfRows=10&bgn_year=2017&type=json`)
    
    if(!responseData.data.body.items){
      setLastData('마지막 페이지입니다.')
      throw Error('더 이상 찾는 정보가 없습니다!')
    }else{
      setLastData('')
      setFood(prev => [...prev,...responseData.data.body.items])
    }
  }catch(err){
    console.error(err)
  }
  setIsLoading(false)

}

  1. 더이상 찾는 데이터가 없을 때 발생할 때 어플리케이션이 종료되는 현상.

Solution. try...catch와 if...else문 사용.

try가 성공했더라도 responseData에 찾는 items가 없다면 Error로 간주하고 handling을 진행한다.

try{
    const responseData = await axios.get(`${API_KEY}&desc_kor=${inputValue}&pageNo=1&numOfRows=10&bgn_year=2017&type=json`)
    if(!responseData.data.body.items){
      setFood([])
      setTotalCount(0)
      setLastData('찾으시는 정보가 없습니다.')
      throw Error('찾으시는 정보가 없습니다.')
    }else{
      
      setLastData('')
      setTotalCount(responseData.data.body.totalCount)
      setFood(responseData.data.body.items);
    }
    
  }catch(err){
    console.error(err)
  }finally{
    setIsLoading(false)
    setIsSearched(true);
  }

++ 인터섹션 옵저버의 type definition

useEffect(() => {
  const option = {
    threshold: 0
  }
  const callback: IntersectionObserverCallback =
 (entry:IntersectionObserverEntry[],observer:IntersectionObserver) => {
    if(entry[0].isIntersecting && food){
      setPageNumber(prev => prev + 1);
      const schadulingNumber = pageNumber + 1
      fetchData(schadulingNumber);
    }
    if(observeTargetRef.current){
      observer.unobserve(entry[0].target);
      observer.observe(observeTargetRef.current);
    }
  }
  const io = new IntersectionObserver(callback,option)
  
  if(observeTargetRef.current){
    io.observe(observeTargetRef.current)
  }
  return () => {
    io && io.disconnect();
  }
},[pageNumber,food])

0개의 댓글