본문 바로가기
카테고리 없음

하나의 state에 2개의 통신을 하고 싶을때?

by cariño 2022. 11. 22.
728x90
반응형

구현하고 싶은 기능은,  map api를 통해서 장소에 대한 북마크를 했을 때 해당 data에 대한 내용을 출력하는거였다. 

문제는 북마크 리스트에 출력이 되는데, 해당 data에 이미지가 없었다. 

뭔가.. 디자인적으로 보기에도 이미지가 없어서 뭔가... 뭔가.. 허전하다고 생각했다. 

 

그래서 결국은,  랜덤이미지 api를 별도로 해주기로 했다. 

 

1. 만든 서버에서 북마크 DATA로 setList에 넣어줌

2. unsplash api를 이용해서 random이미지 setMealThumb에 받기

 

처음 코드는 이랬다. 

function Bookmark() {
    const [list, setList] = useState([])
    const [mealThumb, setMealThumb] = useState([])
    useEffect(() => {
        bookmarkList()
        bookmarkImg()
    }, [])

    const bookmarkList = async () => {
        try {
            const request = await axios.get("http://localhost:3000/store/bookmark")
            setList(request.data)
        }
        catch (err) {
            console.log(err)
        }
    }

    const bookmarkImg = async () => {
        const response = await randomImg.get()
        setMealThumb(randomId)
    }
    
	const randomImg = (idx) => {
    	const randomId = mealThumb.data[Math.floor(Math.random() * 30) + idx].urls.small
		setMealThumb(randomId)
		return randomId
}

return (
        <>
            <h2 css={title}>
                <FontAwesomeIcon icon={faBookmark} style={{ color: "#F4BB44" }} />
                <span>북마크</span>
            </h2>
            <ul css={storeList}>
                {
                    list.map((store, index) => (
                        <Flex css={listItem} key={store.id}>
                            <div className="imgbox">
                                <img src={() => randomImg(index)} alt="" width={200} />
                            </div>
                            <div className="cont">
                                <p>{store.place_name}</p>
                                <div className="info">
                                    <p>{store.road_address_name}</p>
                                    <p>{store.phone}</p>
                                </div>
                            </div>
                        </Flex>
                    ))
                }
            </ul>
        </>
    )
}

export default Bookmark

코드 그대로였다. 

각각 따로따로 호출을 하고 해당 data들을 state에 넣는 방식으로 했다. 

이렇게 해도 정상적으로 작동은 됐었다. 

 

 

    const bookmarkImg = async () => {
        const response = await randomImg.get()
        setMealThumb(randomId)
    }
    
	const randomImg = (idx) => {
    	const randomId = mealThumb.data[Math.floor(Math.random() * 30) + idx].urls.small
		setMealThumb(randomId)
		return randomId
}

 

통신으로 setMealThumb에 데이터를 넣었지만, 하나의 데이터만 여러번 출력됐다. 

이 부분을 보완하고자 아래  img src에 넣는 함수를 바로 실행을 시켰고,  해당 함수는 index를 받아서 배열을 랜덤시켰다. 

 


 

 

## 다시 코드를 재정비 해보자.

저 통신 2개를 굳이 따로 각각의 함수에 넣을 필요가 없잖아?????????????

function Bookmark() {
    const [list, setList] = useState([])

    useEffect(() => {
        bookmarkList()
    }, [])

    const bookmarkList = async () => {
        try {
            const bookmarkRes = await axios.get("http://localhost:3000/store/bookmark")
            const imagesRes = await randomImg.get()
            setList(bookmarkRes.data)            
        	setMealThumb(randomId)
        }
        catch (err) {
            console.log(err)
        }
    }

라고 한게 이 코드였지만, 이미지에서도 객체의 키들을 다 파고파자면 끝이 없었다. 

 

 

어짜피 promise객체이고 비동기를 각 각 한번씩 두번을 실행할게 아니기에  한번에 통신할 수 있는 promise.all을 쓰기로하고, return안에서 map으로 불러오는 state안에 통신으로 받아오는 녀석들 두가지 모두 넣으면 되지 않겠는가?!

 

 

function Bookmark() {
    const [list, setList] = useState([])

    useEffect(() => {
        bookmarkList()
    }, [])

    const bookmarkList = async () => {
        try {
            const [bookmarkRes, imagesRes] = await Promise.all([
                axios.get("http://localhost:3000/store/bookmark"),
                randomImg.get()
            ])
            setList(bookmarkRes.data.map((bookmark, index) => {
                bookmark.place_image = imagesRes.data[index].urls.small
                return bookmark
            })
            )
        }
        catch (err) {
            console.log(err)
        }
    }

1. 먼저 promise.all로 병렬적으로 요청

2.  map을 이용해서  setList에 새로운 데이터 생성

place_image에 넣을 너셕을 return시켜줬다.  결국 이렇게 통신 결과 2개를 이용해서 새로운 데이터 파싱에 성공했뙇!!!

 

 

참고로,  etList부분은 이렇게도 쓸 수 있다.  useState는 비동기임을 생각하자!!!

setList(bookmarkRes.data.map((bookmark, index) => ({
	...bookmark,
	place_image: imagesRes.data[index].urls.small
}))
728x90

댓글