useEffect 의존성 배열에는 state만 들어가는 것이 아니다

Joah·2022년 7월 28일
0

React

목록 보기
24/31


버튼을 한번 클릭했을 때는 ui 렌더링이 안되고 두번 클릭했을 때 렌더링이 된다
한번 클랙했을 때는 searchparams로 url 주소는 변경되지만 그 어떤 state도 변경되지 않기 때문에 리렌더링은 되지 않는다.

원래 작성했던 이슈 가득한 코드

import React, { useEffect, useState } from 'react';
import { useSearchParams, useLocation } from 'react-router-dom';
import Header from '../Header/Header';
import Map from '../Map/Map';
import './Main.scss';

const Main = () => {
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();

  const [dongData, setDongData] = useState([]);

  useEffect(() => {
    fetch('http://서버/regions')
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  }, []);


  const sortStore = storeName => {
    if (location.search.includes('application')) {
      const application = searchParams.get('application');
      setSearchParams({ store: `${storeName}`, application });
    } else {
      setSearchParams({ store: `${storeName}` });
    }

    const url = location.search;
    console.log(url);
    fetch(`http://서버/regions${url}`)
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  };

  const sortApplication = appName => {
    if (location.search.includes('store')) {
      const store = searchParams.get('store');
      setSearchParams({ store, application: `${appName}` });
    } else {
      setSearchParams({ application: `${appName}` });
    }

    const url = location.search;
    fetch(`http://서버/regions${url}`)
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  };
  const showAllStoreData = () => {
    location.search.includes('store', 'application') &&
      searchParams.delete('store', 'application');
    setSearchParams(searchParams);

    fetch(`http://서버/regions${searchParams}`)
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  };

  const showAllAppData = () => {
    location.search.includes('application') &&
      searchParams.delete('application');
    setSearchParams(searchParams);

    fetch(`http://서버/regions?${searchParams}`)
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  };

  if (dongData.length === 0) return;

  return (
    <>
      <Header
        dongData={dongData}
        sortStore={sortStore}
        sortApplication={sortApplication}
        showAllAppData={showAllAppData}
        showAllStoreData={showAllStoreData}
      />
      <Map dongData={dongData} />
    </>
  );
};

export default Main;

수정된 코드

import React, { useEffect, useState } from 'react';
import { useSearchParams, useLocation } from 'react-router-dom';
import Header from '../Header/Header';
import Map from '../Map/Map';
import './Main.scss';

const Main = () => {
  const location = useLocation();

  const [searchParams, setSearchParams] = useSearchParams();

  const [dongData, setDongData] = useState([]);

  const url = location.search;

  useEffect(() => {
    fetch(`http://서버/regions${url}`)
      .then(res => res.json())
      .then(data => {
        setDongData(data.result);
      });
  }, [url]);

  const sortStore = storeName => {
    if (location.search.includes('application')) {
      const application = searchParams.get('application');
      setSearchParams({ store: `${storeName}`, application });
    } else {
      setSearchParams({ store: `${storeName}` });
    }
  };

  const sortApplication = appName => {
    if (location.search.includes('store')) {
      const store = searchParams.get('store');
      setSearchParams({ store, application: `${appName}` });
    } else {
      setSearchParams({ application: `${appName}` });
    }
  };
  const showAllStoreData = () => {
    location.search.includes('store', 'application') &&
      searchParams.delete('store', 'application');
    setSearchParams(searchParams);
  };

  const showAllAppData = () => {
    location.search.includes('application') &&
      searchParams.delete('application');
    setSearchParams(searchParams);
  };

  if (dongData.length === 0) return;

  return (
    <>
      <Header
        dongData={dongData}
        sortStore={sortStore}
        sortApplication={sortApplication}
        showAllAppData={showAllAppData}
        showAllStoreData={showAllStoreData}
      />
      <Map dongData={dongData} />
    </>
  );
};

export default Main;

useEffect에서 의존성 배열 안에 무엇을 작성할 수 있나?
일단 로직을 따져보자

url주소에 변화가 생기면 바로 fetch를 불러라 렌더링은 어차피 fetch함수 안에 dongData를 업데이트 시키는 state가 있기 때문에 리렌더링 될 것이다.

그럼 url 주소에 변화가 생길때마다 fetch함수를 불러오면 된다.
useEffect에서 의존성 배열에 state만 쓸 수 있는게 아니다
의존성 배열에 작성하는 것이 변화할 때마다 useEffect 함수는 작동한다.

그럼 url 을 먼저 선언해주고
url에 변화가 생길 때마다 그 url을 주소 뒤에 넣어 서버에 요청한다.
그 url을 의존성 배열에 작성한다.
즉 의존성 배열에는 변수도 작성할 수 있다.

일단 fetch 함수를 딱 한번만 사용한다는 깔끔함에 걸렸던 병이 나았다.

profile
Front-end Developer

0개의 댓글