[緑野仙踪の製作所NINJA]Ridex環境におけるコメント無限ロードの適用(2)


3-(3)無限スクロールの先端変化


🙏 モード



このコンポーネントのthresholdの値を超える場合は、次のコメントをロードします.
   {!isDisable && (
        <div className={'loading'} ref={target}>
          {loading}
        </div>
      )}
isDisablefalseの場合、DOMに表示されます.=>可視性観察(インポートするコメントo)isDisabletrueの場合、DOMから削除されます.=>可視性観察の停止(取得するコメントx)

1. create observer & onIntersect handler

  const onIntersect = (entries, observer) => {
    if (entries[0].isIntersecting) {
      dispatch(
        loadAllComments({ id: postData.id, page: page, comments: comments }),
      );
      observer.unobserve(target.current); //target.current가 변경 되면
    }
  };
entries[0].isIntersectingは、交差するかどうかのbooleanの値を有する.交差すると、loadAllComments動作を実行します.loadAllCommentsですが、ページ価格から10件のコメントに変更されました.observer.unobserver(target.current)は現在、ターゲットの監視を停止しています.
  useEffect(() => {
    if (page % 10 === 0 && page !== 0) {
      const observer = new IntersectionObserver(
        (entries, observer) => onIntersect(entries, observer),
        { threshold: 1 },
      );
      // 갱신 해주지 않으면 이전의 page에 접근해서 요청함.
      if (target.current) {
        observer.observe(target.current);
      }
      return () => observer && observer.disconnect();
    } else {
      setIsDisable(true);
    }
  }, [page]);
ページの値には、コメントの長さの値があります.(現在コメントの長さは次のコメントから始まる必要があります)
コメントの長さ(=page)を10で割った残りの値が0でない場合、すべてのコメントがインポートされ、setIsDisable(true)で監視対象が削除されます.
10で割った残りの値が0の場合、インポートするコメント、または最後のコメントがあるので、監視を続けます.onIntersect()で更新されたページ値を参照するために、新しいobserverが作成された.
ページを更新するたびに新しい傍観者を再設定すれば、傍観者は蓄積し続けますか?参照が切断され、無効になる可能性があります.=>確認してください

2. update page state

  useEffect(() => {
    setPage(comments.length);
  }, [comments.length]);
comments.lengthの値を依存配列に入れます.価格が変わると、新しいコメントがアップされるので、setPage(comments.length)に価格が更新されます.

3. redux loadAllCommentsSaga

export const loadAllComments = createAction(LOAD_ALL_COMMENTS);
function* loadAllCommentsSaga(action) {
  yield put(startLoading(LOAD_ALL_COMMENTS));
  try {
    const loadAllComments = yield call(
      commentsAPI.getCommentsByPostId,
      action.payload,
    );

    yield put({
      type: LOAD_ALL_COMMENTS_SUCCESS,
      payload: [
        ...action.payload.comments,
        ...loadAllComments.data.allComments,
      ],
    });
  } catch (e) {
    yield put({
      type: LOAD_ALL_COMMENTS_FAILURE,
      payload: e,
      error: true,
    });
  }
  yield put(finishLoading(LOAD_ALL_COMMENTS));
}
yield put({
      type: LOAD_ALL_COMMENTS_SUCCESS,
      payload: [
        ...action.payload.comments,
        ...loadAllComments.data.allComments,
      ],
    });
既存のコメント配列に伴うコメント配列をcomment reducerに接続する.
[LOAD_ALL_COMMENTS_SUCCESS]: (state, { payload }) => {
      return {
        ...state,
        comments: payload.map((comment) => ({
          ...comment,
          Comments: comment.Comments.map((reply) => ({
            ...reply,
            isEditClicked: false,
            isMenuClicked: false,
          })),
          isEditClicked: false,
          isMenuClicked: false,
          isClicked: false,
        })),

        error: null,
      };
immerを使わず、汚れた様子・・・action.payloadに送信されたコメント配列はreduce状態に注入される.

4.感じ

  • onIntersectでstateを使用する場合は、ステータス値を更新するたびにonIntersect関数を再ロードする必要があります.そうでない場合は、過去のページ値を参照してください.

  • 5. Reference


  • 無限スクロールページングの実施例

  • Intersection Observerによる無限スクロール

  • Intersection Observer-要素の可視性を観察する

  • sequalizeクエリー