조건
더보기 버튼을 1번과 2번 누를 때 각각 다른 get 주소 상품 데이터를 불러오고, 3번 누르면 더이상 상품이 없다고 표시한다.
풀이
- '3번 이상 더보기 버튼을 눌렀을 시 더이상 상품 없음 알림'과 '더보기 버튼 클릭 횟수'를 state로 작성했다.
- 버튼 클릭 시 클릭 횟수를 1 증가시키는 콜백함수(handleClick)를 작성해 버튼 이벤트핸들러 안에 넣었다.
- 더보기 버튼 클릭 시 실행될 콜백함수(moreProduct)를 작성했다.
- ajax로 상품데이터를 불러오기 전 loading을 실행시켰다. (setLoading(true);)
- 클릭 횟수에 따른 url을 변수로 만든 후, if문으로 처리하였다. (3번 이상 클릭 시 '상품 없음 알림' true, '로딩' false, ajax 실행을 중단하기 위해 return)
- get으로 url 변수를 불러오고, 가져온 데이터(response.data)를 newProduct에 저장하였다.
- copy 변수를 만들어 기존 상품 목록(props.shoes)와 새로운 상품 목록(newProduct)를 합쳤다.
- 합쳐진 상품목록을 props.setShoes로 shoes를 바꾸어주었다.
- loading을 종료했다. - useEffect 안에 버튼을 클릭할 때마다 (정확히는 click 상태 변수에 변화가 생길 때마다) click횟수가 0이 아닐 시 moreProduct를 실행하도록 사이트 이펙트를 넣었다.
function Main(props){
let [loading, setLoading] = useState(false); // 로딩 상태를 관리하는 상태 변수
let [alertmore, setAlertmore] = useState(false); // 추가 상품 없음 알림 상태를 관리하는 상태 변수
let [click, setClick] = useState(0); // 버튼 클릭 횟수를 관리하는 상태 변수
let handleClick = function(){
setClick(click + 1); // 버튼 클릭 시 클릭 횟수를 1 증가시킴
}
let moreProduct = function() {
setLoading(true); // 로딩 상태를 true로 설정하여 로딩 중임을 표시
let url;
if (click === 1) {
url = 'https://codingapple1.github.io/shop/data2.json'; // 첫 번째 클릭 시 데이터2.json을 가져옴
} else if (click === 2) {
url = 'https://codingapple1.github.io/shop/data3.json'; // 두 번째 클릭 시 데이터3.json을 가져옴
} else if (click > 2) {
setAlertmore(true); // 세 번째 클릭 이상일 경우 추가 상품 없음 알림 상태를 true로 설정하여 알림을 표시
setLoading(false); // 로딩 상태를 false로 설정하여 로딩을 종료
return; // 중복 호출 방지를 위해 함수를 종료
}
axios.get(url) // axios를 사용하여 URL에서 데이터를 가져옴
.then((response) => {
let newProduct = response.data; // 가져온 데이터를 newProduct 변수에 저장
let copyShoes = [...props.shoes, ...newProduct]; // 기존 상품 목록(props.shoes)과 새로운 상품(newProduct)을 합친 새로운 배열을 생성
props.setShoes(copyShoes); // 합쳐진 상품 목록을 설정
setLoading(false); // 로딩 상태를 false로 설정하여 로딩을 종료
})
.catch(() => {
console.log(`실패자`); // 요청 실패 시 에러 처리
});
}
useEffect(() => {
if (click !== 0) {
moreProduct(); // 클릭 횟수가 0이 아니면 moreProduct 함수를 호출하여 추가 상품 가져오기
}
}, [click]); // click 상태 변수가 변경될 때마다 useEffect가 실행되도록 설정
return (
<>
<div className="main-bg" style={{backgroundImage : 'url('+ mainBg +')'}}></div>
<div className="container">
<div className="row">
{loading && <Loading />} // 로딩 중인 경우 Loading 컴포넌트를 렌더링
{alertmore && <Alertmore />} // 추가 상품 없음 알림이 있는 경우 Alertmore 컴포넌트를 렌더링
{
props.shoes.map((a, i) => (<Product shoes={props.shoes} i={i} key={i} />)) // 상품 목록(props.shoes)을 순회하며 Product 컴포넌트를 렌더링
}
</div>
</div>
<button className="" onClick={()=> { handleClick(); }}>더보기</button> // "더보기" 버튼을 클릭하면 handleClick 함수가 실행되도록 설정
</>
)
}
function Loading(){
return (
<div className="alert alert-warning">
상품 로딩중
</div>
)
}
function Alertmore(){
return (
<div className="alert alert-warning">
상품이 더 없습니다.
</div>
)
}
알게 된 점
- ajax를 get할 때 url을 변수 처리 할 수 있다.
- 위 코드에서 useEffect로 moreProduct()함수를 실행처리하지 않고, 더보기 버튼 이벤트핸들러 안에 onClick={()=> {handleClick (); moreProduct(); }}를 넣으면 버튼을 한 번 눌렀을 시 로딩중 버튼만 나오고, 두 번 눌렀을 시 한 번 눌렀을 때 나와야 하는 상품데이터가 불러와지고, 세 번 눌렀을 시 두 번 눌렀을 때 나와야 하는 데이터가 불러와지는 오류가 있었다.
- > 동기/비동기 관련 오류가 난다면 useEffect로 호출시기를 확실하게 주는 것이 좋을듯.. 왜인지 생각중
출처 : 코딩애플 https://codingapple.com/
'⚛️ React > 문제풀기 (코딩애플: React)' 카테고리의 다른 글
React : 탭 내용 fade되도록 만들기 (+class에 변수 넣기) (0) | 2023.06.15 |
---|---|
React : 탭 만들기 (if else, array로 만들기) + props 귀찮을 때 팁 (0) | 2023.06.12 |
React : ajax 상품 불러오기 전 로딩중 만들기 (0) | 2023.05.31 |
React : 더보기 버튼 누르면 ajax axios로 상품 더 가져오기 (1) | 2023.05.31 |
React : 숫자가 아닌 걸 치면 alert 뜨는 input 만들기 (0) | 2023.05.26 |