ChungHa Brocher_5 : 2021.06.06 Change Promise to Array , using 'useEffect'
4753 ワード
Status Quo
1) PicturesData
export const PictureDatas = (async function () {
const picutureDatas = await Axios.post('/api/album/images')
.then(res=> {
const pictures = res.data.imgDatas.slice()
// shuffle Array
for (let i = pictures.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[pictures[i], pictures[j]] = [pictures[j], pictures[i]];
}
return pictures
})
return picutureDatas
})()
2) GetpictureData ~~
export default function GetPictureData(pictureNum: number) {
~ ~
~ ~
const PictureDatasLength = PictureDatas.length - 1;
~~
}
Error
Promise<any> does not have 'length' in it's form
Purpose
have to make return type as normal array so that it has 'length' attribute in it
Solution
1) Put "getPictsFromDB" Func that retrieves data from db into "GetPictureData" Component
2) Make it as async function in order to apply 'await' to axios and wait until all the datas are retrieved
3) Apply 'useCallback' to "getPictsFromDB" Func, since we are going to put it to 'dependency array'
4) Put it into 1st useEffect
below code will run as soon as the component renders with getPictsFromDB() in the dependency array ,
since we applied 'useCallback' to 'getPictsFromDB()' ,
getPictsFromDB() will not change, which means
below "useEffect()"will only run at initial moment
5) Put retrieved data (pictureDatas) into 2nd useEffect dependency Array
At the initial rendering, there will be no data in 'pictureDatas', since < 1st useEffect > has not run yet,
but as soon as 1st useEffect runs , actual picture datas will be set to "pictureDatas", which means 2nd useEffect is able to render the pictures to pages
useEffect(() => {
getPictsFromDB();
}, [getPictsFromDB]);
Full Code
import { useEffect, useState, useCallback } from "react";
import { ImageDataType } from "assets/data/types";
import Axios from "axios";
export default function GetPictureData(pictureNum: number) {
const [loading, setLoading] = useState(true);
const [pictureDatas, setPictureDatas] = useState<Array<any>>([]);
const [pictures, setPictures] = useState<Array<ImageDataType>>([]);
const [curPictNum, setCurPictNum] = useState(0);
const [hasMore, setHasMore] = useState(false);
const PictureDatasLength = pictureDatas.length;
const getPictsFromDB = useCallback(
async function () {
const datas: Array<any> = await Axios.post("/api/album/images").then(
(res) => res.data.imgDatas
);
const pictures = datas.slice();
// shuffle Array
for (let i = pictures.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[pictures[i], pictures[j]] = [pictures[j], pictures[i]];
}
setPictureDatas(pictures);
},
[setPictureDatas]
); // 변하지 않게 해주려고, setLoading 이라는 다소 관계없는 함수 넣었다
// 사진 정보 db에서 가져오기
useEffect(() => {
getPictsFromDB();
}, [getPictsFromDB]);
// Intersection observer
useEffect(() => {
// 위의 useEffect 함수를 통해 pictureData가 불러와지면 해당 함수를 실행한다
// 최대 이미지 숫자 개수를 넘어가지 않도록 한다
pictureNum =
pictureNum > PictureDatasLength ? PictureDatasLength : pictureNum;
// setLoading(true)
setPictures((prevPicts) => {
return [...prevPicts, ...pictureDatas.slice(curPictNum, pictureNum)];
});
setHasMore(pictureDatas.slice(curPictNum, pictureNum).length > 0);
setCurPictNum(pictureNum);
// setLoading(false)
}, [pictureNum, pictureDatas]);
return { loading, pictures, hasMore };
}
Reference
この問題について(ChungHa Brocher_5 : 2021.06.06 Change Promise to Array , using 'useEffect'), 我々は、より多くの情報をここで見つけました https://velog.io/@dhsys112/ChungHa-Brocher3-2021.06.06-Change-Promiseany-to-Array-using-useEffectテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol