드디어 정말 정말 긴 시간동안 해결이 되지 않던 서평 공간에 사진이 띄워지지 않는 오류 문제를 해결하였다.
문제는 서평 공간을 띄울 때 백엔드로 부터 불러오는 review 데이터 값을 이용해서 서평 내용은 map을 이용해 쉽게 보여줄 수 있었다. 하지만, 책과 관련된 정보는 review로 부터 isbn만 불러오기 때문에 먼저 카카오 api를 통해 isbn을 이용해 각 책 이미지와 제목을 불러온 후 함께 띄워줘야 했다. 하지만 다음과 같이 img 컴포넌트에 src 속성을 카카오 api를 불러오는 함수를 넣어줄 수가 없어 해결이 계속 되지 않았다.
// 카카오 api 통해 책 이미지 return 함수
async function booksdata(isbn) {
isbn.indexOf(' ') !== -1 ? isbn = isbn.slice(11) : isbn = isbn
const params = {
target: 'isbn',
query: isbn,
size: 1,
};
const {data: {documents}} = await ResultApi(params);
return (documents[0].thumbnail)
}
//src 에 카카오 api 함수 적용
{datas && datas.map((data, idx)=> <Storeform key={data.id} onClick={() => moveDetail(data)}>
<Bookimg src={() => booksdata(data.bookId)}></Bookimg>
위와 같이 src 속성에 함수를 넣어줄 수 없었다.
처음엔 src에 함수를 넣을 수 없다는 걸 확인 하고 Bookimg 컴포넌트를 div로 바꾸고, props를 통해 함수를 전달해주어 이미지 링크를 styled-component의 background-image에 전달해 주었다. 하지만 문제가 해결되지 않았다.
결국, map을 통해 전달 받은 각 data값으로는 이미지와 제목을 불러 올 수 없다고 판단하였다. 그래서 백엔드로 부터 불러온 전체 reviewdata에서 for문을 이용해 각 data의 책 id값을 카카오 api 함수의 인자로 넣어주었다. 이후 불러온 각 책의 이미지와 제목들을 배열 안에 넣어 map가 제공하는 index를 이용해 서평 공간에 띄워주는 방법을 생각하였다.
const [thumbnail, setThumbnail] = useState([])
const [title, setTitle] = useState([])
//백엔드로 부터 reviewdata를 불러와 datas에 저장
useEffect(()=>{
axios.get('http://127.0.0.1:8000/review/')
.then((response) => {
setDatas(response.data)
console.log((response.data))
setNoData(false)
}).catch((error)=>{
console.log(error)
})
},[])
//datas값이 변경되면(백엔드로 부터 데이터를 불러오면) 카카오 api 함수 불러오기
useEffect (() => {
if (datas !== []){
for (let i=0; i<datas.length; i++){
booksdata(datas[i].bookId)
}
}
}, [datas])
//책 id로 각 리뷰의 이미지와 제목 가져오고, 배열 안에 넣기
async function booksdata(isbn) {
isbn.indexOf(' ') !== -1 ? isbn = isbn.slice(11) : isbn = isbn
const params = {
target: 'isbn',
query: isbn,
size: 1,
};
const {data: {documents}} = await ResultApi(params);
setThumbnail((olddata) => [...olddata, documents[0].thumbnail])
setTitle((olddata) => [...olddata, documents[0].title])
}
return (<ul>
{datas && datas.map((data, idx)=> <Storeform key={data.id} onClick={() => moveDetail(data)}>
<Bookimg bground={thumbnail[idx]}></Bookimg>
<Booktitle>{title[idx]}</Booktitle>
)})
</ul>
하지만 이렇게 하였을 때 생기는 또 다른 문제는 이미지와 책 제목의 순서가 페이지 새로고침 할 때마다 달라진다는 것이었다. 저장된 서평 순서대로 나오지 않고 이미지와 제목의 순서가 뒤죽박죽으로 배열되어 보여진다는 것이었다. 하지만 배열은 순서가 있기에 배열 안에 데이터를 집어넣으면서 생기는 문제는 아니라고 생각했다.
문제는 for 문을 이용해서 각 리뷰 데이터의 카카오 api 함수를 호출할 때 비동기 특성 때문에 함수들이 앞 순서의 함수가 다 불러와지기 전에 호출된다는 것에 있었다.
useEffect (async() => {
if (datas !== []){
for (let i=0; i<datas.length-60; i++){
await booksdata(datas[i].bookId)
}
}
}, [datas])
각 함수에 await를 걸어주었고, 서평 이미지와 제목을 순서대로 잘 불러올 수 있었다.