React+Redux) redux 데이터 갈아끼우기

이해원·2022년 4월 4일
0

infinity scroll (무한스크롤)은 어떤 특정 시점에 이르면 게시물을 더 호출하는 로직이었다면

나는 버튼을 누르면 안의 게시물이 다음 게시물로 바뀌게 하고 싶었다. 리덕스를 사용하고 있었기 때문에 미들웨어에서 firestore에서 다음게시물을 가지고 오는것을 처리하고 리듀서에서 지금있는 보여지는 게시물 갯수만큼 그대로 다음차례의 게시물로 바꾸어 주었다.

위치) redux > modules > post.js
//action type
const CUT_POST ='CUT_POST';

//action creator
const cutPost = createAction(CUT_POST,(post_list,paging)=>({post_list,paging,}))

//middleware
const getRandomPostFirebase = (start = null, size = 4) => {
  return function (dispatch, getState, { history }) {
    let _paging = getState().log.paging;

    if (_paging.start && !_paging.next) {
      return;
    }

    dispatch(loading(true));
    const postDB = firestore.collection("post");

    let query = postDB.orderBy("insert_dt", "desc");

    if (start) {
      query = query.startAt(start);
    }

    query
      .limit(size + 1)
      .get()
      .then((docs) => {
        let post_list = [];

        let paging = {
          start: docs.docs[0],
          next:
            docs.docs.length === size + 1
              ? docs.docs[docs.docs.length - 1]
              : null,
          size: size,
        };

        docs.forEach((d) => {
          let all_data = d.data();

          //['comment_count','contents', ..]
          let post = Object.keys(all_data).reduce(
            (acc, cur) => {
              if (cur.indexOf("user_") !== -1) {
                return {
                  ...acc,
                  user_info: { ...acc.user_info, [cur]: all_data[cur] },
                };
              }
              return { ...acc, [cur]: all_data[cur] };
            },
            { id: d.id, user_info: {} }
          );
          post_list.push(post);
        });
        //4개 넘어 갔으니까 마지막꺼 하나 없애기
        post_list.pop();

        dispatch(cutPost(post_list, paging));
      });
  };
};

//reducer

export default handleActions(
  {
  [CUT_POST]: (state, action) =>
      produce(state, (draft) => {
        draft.post_list=action.payload.post_list;

        draft.post_list = draft.post_list.reduce((acc, cur) => {
          if (acc.findIndex((a) => a.id === cur.id) === -1) {
            return [...acc, cur];
          } else {
            acc[acc.findIndex((a) => a.id === cur.id)] = cur;
            return acc;
          }
        }, []);

        draft.is_loading = false;
        draft.paging = action.payload.paging;
      }),
       },
  initialState
);

//action creator export
const actionCreators = {
  getRandomPostFirebase,
};

export { actionCreators };

추가하는 경우에는 이런식으로 draft.post_list.push(...action.payload.post_list);
push 해서 어레이에 spread 연산자로 넣어주는데

원래있던 data에 추가가 아니라 data 자체를 갈아끼우는 경우에는 위의 리듀서에서 보듯이 draft.post_list = action.payload.post_list;
이런식으로 post_list 자체를 바꾸면된다

이제는 이값을 불러다 쓸 component 에서 useSelector로 state 를 가지고온다.


import { actionCreators as logActions } from "../redux/modules/log";
import { useSelector, useDispatch } from "react-redux";

const Map = (props) => {
  const dispatch = useDispatch();
  const post_list = useSelector((state) => state.log.post_list);
  const paging = useSelector((state) => state.log.paging);

  console.log(post_list);
  
  React.useEffect(() => {
    if (post_list.length < 2) {
      dispatch(logActions.getRandomPostFirebase());
    }
  }, []);

  const renewPostHandler = () => {
    dispatch(logActions.getRandomPostFirebase(paging.next));
  };

  return (
    <div className={classes.wrap}>
          <button className={classes.btn__redirect} onClick={renewPostHandler}>
            <AutorenewIcon />
          </button>
          <div className={classes.logs__wrapper}>
            {post_list &&
              post_list?.map((p, idx) => (
                <MapPost key={p.id + "post_list"} {...p} />
              ))}
          </div>
     </div>
  );
};
profile
미어캣입니당

0개의 댓글