부수효과란?
앱이 제대로 동작하기 위해 실행되어야 하지만 현재의 컴포넌트 렌더링 과정에 직접적인 영향을 미치지는 않는 작업
sample
1. useEffect() 사용 장소가 나열된 리스트를 사용자의 위치와 가까운 순으로 나열하고 싶다.
위치 코드는 있는 상태
더보기
function toRad(value) {
return (value * Math.PI) / 180;
}
function calculateDistance(lat1, lng1, lat2, lng2) {
const R = 6371;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lng2 - lng1);
const l1 = toRad(lat1);
const l2 = toRad(lat2);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(l1) * Math.cos(l2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const d = R * c;
return d;
}
export function sortPlacesByDistance(places, lat, lon) {
const sortedPlaces = [...places];
sortedPlaces.sort((a, b) => {
const distanceA = calculateDistance(lat, lon, a.lat, a.lon);
const distanceB = calculateDistance(lat, lon, b.lat, b.lon);
return distanceA - distanceB;
});
return sortedPlaces;
}
useEffect(() => {
// 사용자의 위치 호출
navigator.geolocation.getCurrentPosition((position) => {
// 정렬된 장소
const sortedPlaces = sortPlacesByDistance(
AVAILABLE_PLACES,
position.coords.latitude, // 위도
position.coords.longitude // 경도
);
setAvailablePlaces(sortedPlaces); // 사용자와 가까운 sortedPlaces로 업데이트
});
}, []);
- 무한루프의 문제가 있어서 useEffect()를 사용
- useEffect로 함수가 실행되는 시점을 설정
- 모든 부수효과가 useEffect를 사용하진 않으면 useEffect의 과한 사용은 좋지 않음.
- 필요한 것이 아니라면 useEffect 사용을 자제
2. useEffect() 미사용 사용자가 선택한 장소를 스토리지에 추가하기
function handleSelectPlace(id) {
setPickedPlaces((prevPickedPlaces) => {
if (prevPickedPlaces.some((place) => place.id === id)) {
return prevPickedPlaces;
}
const place = AVAILABLE_PLACES.find((place) => place.id === id);
return [place, ...prevPickedPlaces];
});
// 사용자가 선택한 장소 스토리지에 추가하기
const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
if (storedIds.indexOf(id) === -1) {
localStorage.setItem(
"selectedPlaces",
JSON.stringify([id, ...storedIds])
);
}
}
function handleRemovePlace() {
setPickedPlaces((prevPickedPlaces) =>
prevPickedPlaces.filter((place) => place.id !== selectedPlace.current)
);
modal.current.close();
// 사용자가 삭제한 장소 스토리지에 삭제하기
const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
localStorage.setItem(
"selectedPlace",
JSON.stringify(storedIds.filter((id) => id !== selectedPlace.current))
);
}
- 함수 안에 있어서 useEffect()를 사용하지도 못할뿐더러 상태업데이트 코드가 아니라서 사용하지 않음.
불필요한 useEffect 예시
useEffect(() => {
const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
const storedPlaces = storedIds.map((id) =>
AVAILABLE_PLACES.find((place) => place.id === id)
);
setPickedPlaces(storedPlaces);
}, []);
useEffect없는 바른 사용법
function App() {
const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
const storedPlaces = storedIds.map((id) =>
AVAILABLE_PLACES.find((place) => place.id === id)
);
const modal = useRef();
const selectedPlace = useRef();
const [availablePlaces, setAvailablePlaces] = useState([]);
const [pickedPlaces, setPickedPlaces] = useState(storedPlaces); // 기본 상태를 storedPlaces로 함
useCallback()
useCallback은 value를 리턴함.
주변 컴포넌트 함수가 다시 실행되는 경우마다 재 생성되지 않는 방식으로 리턴함.
안 쪽에 있는 함수가 재생성 되지 않게 하지만 메모리로서 내부에 저장.
해당 함수가 재사용 될 때마다 메모리로서 저장된 그 함수를 재사용함.
const handleRemovePlace = useCallback(function handleRemovePlace() {
setPickedPlaces((prevPickedPlaces) =>
prevPickedPlaces.filter((place) => place.id !== selectedPlace.current)
);
setModalIsOpen(false);
// 사용자가 삭제한 장소 스토리지에 삭제하기
const storedIds = JSON.parse(localStorage.getItem("selectedPlaces")) || [];
localStorage.setItem(
"selectedPlaces",
JSON.stringify(storedIds.filter((id) => id !== selectedPlace.current))
);
}, []);
'언어 > React.js' 카테고리의 다른 글
useCallback() (0) | 2024.10.22 |
---|---|
[React] 내가 보려고 쓴 리액트 (0) | 2023.10.26 |
[React] useEffect() (0) | 2023.10.24 |
[React] api 설치 (0) | 2023.10.24 |
[React] react-router-dom 오류 (2) | 2023.10.17 |