忘れないように、メモ書き。
API
SQL は、SQLite を使っていました。
SELECT * FROM Hoge WHERE fuga="fuga1";
のような SQL文 を、LIMIT & OFFSET で 10件程度に分割する。
SELECT * FROM Hoge WHERE fuga="fuga1" LIMIT 10 OFFSET 10;
これに URL を付与 (Railsなら routes.rb、Djangoなら urls.py の url patterns、Express なら app.get('url', function(req, res) => ){} ) して、http://hoge-api.com/hoges?offet=num
から hoge の num の offset からのデータを取得できるようにする。
Redux
Redux Thunk を使ってかく。
export const CONCAT_HOGE_SUCCESS = "CONCAT_HOGE_SUCCESS"
export const CONCAT_HOGE_FAIL = "CONCAT_HOGE_FAIL"
export const concatHoge = (offset) => {
return (dispatch) => {
axis({
url: "http://hoge-api.com/hoges?offet=" + offset,
method: "POST"
}).then((response) => {
let response_status = response["data"]["status"]
if (response_status == "ok"){
let response_data = response["data"]["hoge"]
dispatch(concatHogeSuccess(response_data))
} else {
dispatch(concatHogeFail())
}
})
}
}
const concatHogeSuccess = (data) => {
return{
type: CONCAT_HOGE_SUCCESS,
data: data,
}
}
const concatHogeFail = () => {
return {
type: CONCAT_HOGE_FAIL,
}
}
import {CONCAT_HOGE_SUCCESS, CONCAT_HOGE_FAIL} from "../actions";
export const hoge = (state=[], action) => {
switch(action.type){
// ... 省略
case CONCAT_HOGE_SUCCESS:
return [...state, ...action.data]
case CONCAT_HOGE_FAIL:
return state
}
}
これで、下のようなReactのコードで、ボタンを押せば、パージネーション の続きが見れるようになる。
import {useState, useRef} from "react"
import {useDispatch, useSelector} from "react-redux"
// ... 省略
const hoge = () => {
const dispatch = useDispatch()
const hoge = useSelector(state => state.hoge)
// setTimeout 用 の state
const [offset, setOffset] = useState(2) /* API の URL に合わせる */
const offsetRef = useRef(offset)
offsetRef.current = offset
// ... 省略
const onClickHogeOffset = () => {
dispatch(offset)
let next_offset = offset + 1
setOffset(next_offset)
}
return {
<>
{hoge.map((item) => {
// ... 省略
})}
<div className="pagination-next-area">
<button onClick={() => onClickHogeOffset()}>
もっと見る
</button>
</div>
</>
}
}
React
javascript の event の scroll を使う。
上の Reactのファイル に、まず useEffect で 初期のスクロール位置を取得し、window に onScrollPagination イベントを追加します。
import {useState, useRef, useEffect} from "react"
// ... 省略
const hoge = () => {
// ... 省略
const [paginationPos, setPaginationPos] = useState(0)
const paginationPosRef = useRef(paginationPos)
paginationPosRef.current = paginationPos
// ... 省略
useEffect(() => {
window.setTimeout(initializePagination, 1000) /* 描画が遅れる問題 */
})
// ... 省略
const initializePagination = () => {
var pagination_area = document.getElementsByClassName("pagination-next-area")[0]
setPaginationPos(pagination_area.offsetTop)
window.addEventListener("scroll", onScrollPagination)
}
const onScrollPagination = () => {
// ここに scroll イベントを実装する
}
}
window の位置が、上記の paginationPos を越した場合に、上記の dispatch(concatHoge(offset))
を含んだ onClickHogeOffset
を発火させる。
import concatHoge from "./actions"
// ... 省略
const onScrollPagination = () => {
if (window.scrollY + window.innerHeight > paginationPosRef.current ) {
onClickHogeOffset()
var pagination_area = document.getElementsByClassName("pagination-next-area")[0]
pagination_area.removeEvent("scroll", onScrollPagination)
// PaginationPos を更新する
setPaginationPos(pagination_area.offsetTop)
window.addEventListener("scroll", onScrollPagination)
}
}
以上でした。