redux 更改其中一个Map子项的状态将导致重新渲染所有其他子项

2ul0zpep  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(128)

Newsfeed.js

import React, { useEffect, useState } from "react";
import { Box, Center, useColorMode } from "@chakra-ui/react";

import NewsFeedPost from "@/components/newsfeed/NewsFeedPost";
import { useDispatch, useSelector } from "react-redux";
import { getNewsFeedPost } from "../redux/asyncActions/postAction";
import PostCardSkeleton from "../components/skeleton/PostCardSkeleton";
import { axiosInstance } from "../axiosConfig";
import AddNewsFeed from "../components/newsfeed/AddNewsFeed";
import PostLayout from "../components/large/PostLayout";
import {
  loadedMore,
  setError,
  setMeta,
  setPostExtend,
} from "../redux/slices/postSlice";
import InfiniteScroll from "react-infinite-scroller";
import Loading from "../components/small/Loading";
import { commonSlidercss, darkSlidercss } from "../GlobalStyles";
import { setCurrentPage } from "../redux/slices/siteSlice";
import NoPostYet from "../components/small/NoPostYet";
import { useNavigate, useSearchParams } from "react-router-dom";
import { LIMIT } from "../constants/pagination";
import HelmetWrapper from "../components/small/HelmetWrapper";

const NewsFeed = (query) => {
  const dispatch = useDispatch();
  const postState = useSelector((state) => state.postReducer);
  const newsFeeds = postState.newsFeedPosts;
  const metaInfo = postState.postMeta;
  const [endReached, setEndReached] = useState(false);
  const { colorMode } = useColorMode();
  let [searchParams] = useSearchParams();
  const [categoryId, setCategoryId] = useState("");
  const [streamId, setStreamId] = useState("");
  const [tag, setTag] = useState("");
  const [totalPosts, setTotalPosts] = useState(0);

  const navigate = useNavigate();

  useEffect(() => {
    if (query) {
      navigate(query);
    }
  }, []);

  useEffect(() => {
    getTotal();
  }, []);

  useEffect(() => {
    const stream_id = searchParams.get("stream_id") || "";
    const category_id = searchParams.get("category_id") || "";
    const tag = searchParams.get("tag") || "";
    const searchKeyword = searchParams.get("keyword") || "";
    setCategoryId(category_id);
    setStreamId(stream_id);
    setTag(tag);
    dispatch(getNewsFeedPost(searchKeyword, category_id, stream_id, tag));
    dispatch(setCurrentPage("NewsFeed"));
    return () => {
      dispatch(setPostExtend(false));
      dispatch(setError(null));
    };
  }, [searchParams]);

  const getTotal = async () => {
    try {
      const res = await axiosInstance.get(`post`);
      setTotalPosts(res?.data?.post?.total);
    } catch (e) {
      console.log("Something went wrong while fetching total posts", e);
    }
  };

  const loadFunc = async () => {
    if (metaInfo && metaInfo?.next_page_url) {
      const res = await axiosInstance.get(
        `post?category=${categoryId}&stream=${streamId}&tag=${tag}&page=${
          metaInfo?.current_page + 1
        }&limit=${LIMIT}&published=${true}`
      );
      dispatch(
        setMeta({
          current_page: res?.data?.post?.current_page,
          next_page_url: res?.data?.post?.next_page_url,
        })
      );
      dispatch(loadedMore(res?.data?.post?.data));
    } else {
      setEndReached(true);
    }
  };

  // I see this console also getting printed when I add new comment in one of the post
  console.log("hey this is newsfeed let'see if I render again");

  return (
    <>
      <HelmetWrapper title="NewsFeed - Alumsity" />

      <PostLayout>
        <Box
          style={{
            overflowY: "auto",
            height: "calc(100vh - 120px)",
          }}
          css={colorMode === "light" ? commonSlidercss : darkSlidercss}
          pr={{ base: "6px", lg: "0.8rem" }}
          pb={{ lg: "2vh" }}
          overflowX="hidden"
        >
          <AddNewsFeed />
          {postState.isLoading ? (
            <>
              <PostCardSkeleton />
              <PostCardSkeleton />
            </>
          ) : newsFeeds ? (
            <InfiniteScroll
              pageStart={0}
              loadMore={loadFunc}
              hasMore={true || false}
              useWindow={false}
              loader={
                metaInfo &&
                metaInfo?.next_page_url && (
                  <div className="loader" key={0}>
                    <Loading />
                  </div>
                )
              }
            >
              {newsFeeds?.length > 0 ? (
                newsFeeds?.map((li) => <NewsFeedPost data={li} key={li?.id} />)
              ) : (
                <NoPostYet type="newsfeed" totalPosts={totalPosts} />
              )}
            </InfiniteScroll>
          ) : (
            <Center>No Post Found</Center>
          )}
        </Box>
      </PostLayout>
    </>
  );
};

export default NewsFeed;

NewsFeedPost.jsx

const NewsFeedPost = ({ data }) => {
  const [showComment, setShowComment] = useState(false);
  const [comments, setComments] = useState([]);
  const [commentsCount, setCommentsCount] = useState(0);
  const [currentPage, setCurrentPage] = useState(1);
  const [nextPage, setNextPage] = useState(null);
  const boxShadow = useColorModeValue(
    "0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06)",
    "none"
  );
  const borderColor = useColorModeValue("#EAECF0", "#424242");

  const bg = useColorModeValue("white", COLORS.darkGray);
  const dispatch = useDispatch();

  useEffect(() => {
    if (showComment && data?.id) {
      getComments(data?.id);
    }
  }, [showComment, data?.id]);

  const getComments = async (id, PAGE) => {
    try {
      const res = await axiosInstance.get(
        `comment/post/${id}?limit=${5}&page=${PAGE}`
      );
      setComments((prev) => [...prev, ...res?.data?.comment?.data]);
      setCurrentPage(res?.data?.comment?.current_page);
      setNextPage(res?.data?.comment?.next_page_url);
      setCommentsCount(res?.data?.comment?.total);
    } catch (err) {
      console.log("error is", err);
      dispatch(addNotice("Something went wrong"));
    }
  };

  const loadMoreComments = () => {
    if (nextPage) {
      getComments(data?.id, currentPage + 1);
    }
  };

  const addNewComment = (newComment) => {
    console.log("new comment is here", newComment);
  };

  console.log("the data coming is", data);
  console.log("the comments are", comments);

  return (
    <Box >
      <Flex>
        <Link to={`/post-detail/${data?.id}`}>
          <Text fontWeight="400" fontSize={["sm", "md"]}>
            {data?.title}
          </Text>
        </Link>

        <Menu>
          <MenuButton>
            <BsThreeDots color="#7B6CB4" />
          </MenuButton>
          <Portal>
            <PostOptions data={data} />
          </Portal>
        </Menu>
      </Flex>
      <Flex direction="row" align="center" justify="space-between">
        <Box>
          <PostInfo data={data} />
        </Box>
        {data.tags && <PostTag tags={data?.tags} />}
      </Flex>
      <PostContent data={data} />
      <Divider mt="1rem" mb="0.5rem" />
      <Flex
        direction="row"
        justify={{ base: "start", sm: "space-between" }}
        mt="1rem"
        align="center"
        gap={["6%", 0]}
      >
        <CommentBox
          data={data}
          postDetail={false}
          addCommentNew={(newComment) => addNewComment(newComment)}
        />

        <Box width={{ base: "45%", sm: "45%", lg: "40%" }}>
          <Flex
            direction="row"
            justify="space-around"
            position="relative"
            gap={[3, 0]}
          >
            <PostLikeUnLike data={data} />

            <DataIconCount
              icon="AiFillMessage"
              count={data?.comments_count}
              onClick={() => {
                setShowComment((prev) => !prev);
              }}
            />

            <SocialShares postId={data?.id} />
          </Flex>
        </Box>
      </Flex>
      {comments?.length > 0 &&
        comments?.map((li) => (
          <Box
            zIndex="10"
            key={li?.id}
            display={showComment ? "block" : "none"}
          >
            <PostComment data={li} />
          </Box>
        ))}

      {nextPage && showComment && (
        <Button
          borderRadius="10px"
          width="full"
          mt="1.5rem"
          fontSize="12px"
          fontWeight="400"
          onClick={() => loadMoreComments(data)}
        >
          View More Comments
        </Button>
      )}
    </Box>
  );
};

export default NewsFeedPost;

CommentBox.jsx

import { Box, Input } from "@chakra-ui/react";
import React from "react";
import { useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { axiosInstance } from "../../axiosConfig";
import { addNewComment, setResponse } from "../../redux/slices/postSlice";
import { addNotice } from "../../redux/slices/userSlice";
import AddPicker from "../small/AddPicker";

const CommentBox = ({
  data,
  addCount,
  postDetail = true,
  addCommentNew = null,
}) => {
  const [commentInput, setCommentInput] = useState("");
  const dispatch = useDispatch();

  const addMyComment = async (e, id) => {
    e.preventDefault();
    let data = {
      post_id: id,
      content: commentInput,
    };
    try {
      const res = await axiosInstance.post(`comment`, data);
      if (postDetail === true) {
        dispatch(addNewComment(res?.data?.comment));
      } else if (!postDetail) {
        addCommentNew(res?.data?.comment);
      }
      dispatch(addNotice(res.data.message));
      dispatch(setResponse(true));
      addCount && addCount();
      setCommentInput("");
    } catch (e) {
      console.log(e);
      dispatch(addNotice("Something went wrong while adding comment"));
    }
  };

  return (
    <Box w={{ base: "49%", sm: "50%", md: "70%", lg: "70%" }}>
      <form
        onSubmit={(e) => addMyComment(e, data?.id)}
        style={{ position: "relative" }}
      >
        <Input
          value={commentInput}
          onChange={(e) => setCommentInput(e.target.value)}
          fontSize={["9px", "10px", "xs", "xs"]}
          placeholder="Add Response..."
          // zIndex={0}
        />
        <AddPicker setInput={setCommentInput} />
      </form>
    </Box>
  );
};

export default CommentBox;

我将所有来自api的postMap到NewsFeedPost组件。因为我必须根据postid显示注解,所以我为该组件中的每个Mappost创建了commentsshowComment状态。
每当我添加新的评论到一个职位,所有其他子得到重新呈现和console.log("the data coming is")和一个以下得到打印的所有Map职位。例如,如果我添加新的评论的第一个职位,console.log应该只打印该组件,但它继续得到打印的所有其他Map职位,如果有4个职位,我得到控制台日志6次
我想知道获取newsfeed中每个帖子的评论的最佳方法是什么?虽然更改一个Map子级的状态不会影响其他子级,但是每个帖子的状态是绑定在一起的吗?还是将数组Map到组件会为每个帖子创建新的状态?

egdjgwm8

egdjgwm81#

你能试试这个再测试一次吗?

export default React.memo(CommentBox)

相关问题