팔로우, 언팔로우 하기

개발공부·2022년 12월 22일
0

* 결과

1) (글 쓴 본인은 제외한) 사람들 팔로우, 언팔로우

2) 내 정보에서 언팔로우

3) 내 정보에서 맞팔로우

* 핵심

  • 게시글이 있는 쪽의 팔로우, 언팔로우와 내 정보에서 언팔로우, 맞팔로우는 같은 코드 사용
  • 본인은 팔로우 할 수 없도록 함
  • 팔로우, 언팔로우 할 떄마다 팔로잉, 팔로워 수가 변해야 함

* 코드

<post 관련>

[pages/post.js]

import { useDispatch, useSelector } from "react-redux";

 const dispatch = useDispatch();
  const { me } = useSelector((state) => state.user);
  const { mainPosts } = useSelector((state) => state.post);
  
 return ( 
{mainPosts.map((post, index) => {
              return (
                <PostCard key={post.id} post={post} index={index} me={me} />
                //props로 post, me값 전달
              );
            })}
)

[components/PostCard.js]

const PostCard = ({ post, index, me }) => {
  const dispatch = useDispatch();
  
  const id = useSelector((state) => state.user.me?.id);
  const liked = post.Likers?.find((v) => v.id === id);
  const isFollowing = me?.Followings.find((v) => v.id === post.User.id);
  
  return (
  {id === post.UserId ? null : (
                  <p className="text-sm">
                    {isFollowing ? "언팔로우" : "팔로우"}
                  </p>
                )})

<profile 관련>

[pages/profile.js]

const dispatch = useDispatch();
const { me } = useSelector((state) => state.user);
const { mainPosts } = useSelector((state) => state.post);
const { wordLists } = useSelector((state) => state.word);


return (
<Profile me={me} postResult={postResult} wordResult={wordResult} />
)

[components/Profile.js]

const Profile = ({ me, postResult, wordResult }) => {
  const dispatch = useDispatch();
  
 const [followerModal, setFollowerModal] = useState(false);
  const [followingModal, setFollowingModal] = useState(false);
  
  //버튼 누르면 각각 setFollowerModal, setFollowingModal이 true가 되도록 함
  
  return (
  {followingModal ? (
        <FollowingModal
          setFollowingModal={setFollowingModal}
          followingsInfo={me?.Followings}
        />
      ) : null}
      {followerModal ? (
        <FollowerModal
          setFollowerModal={setFollowerModal}
          followersInfo={me?.Followers}
          followingsInfo={me?.Followings}
        />
      ) : null}
  )

* 반복문 안에서 onClick(반복문 데이터가 들어가는 경우)

- 고차함수 이용

[components/FollowerModal.js]

const FollowerModal = ({ setFollowerModal, followersInfo, followingsInfo }) => {
  const onClickFollowUp = (id) => () => {
    dispatch(followRequest(id));
  };

return (
{followersInfo.map((follower) => {
                                return (
                                  <div
                                    key={follower.id}
                                    className="mt-3 flex items-center space-x-4"
                                  >
                                    <div className="flex-shrink-0">
                                      <img
                                        className="ml-2 w-8 h-8 rounded-full"
                                        src="/docs/images/people/profile-picture-1.jpg"
                                        alt="Neil image"
                                      />
                                    </div>
                                    <div className="flex-1 min-w-0">
                                      <p className="text-sm font-medium text-gray-900 truncate">
                                        {follower.nickname}
                                      </p>
                                      <p className="text-sm text-gray-500 truncate dark:text-gray-400">
                                        {follower.email}
                                      </p>
                                    </div>

                                    {followingsInfo.find(
                                      (following) =>
                                        following.id === follower.id
                                    ) ? null : (
                                      <button
                                        onClick={onClickFollowUp(follower.id)}
                                        className="bg-light-green text-white hover:bg-light-beige hover:text-red-500 rounded inline-flex items-center text-base font-semibold text-gray-900"
                                      >
                                        맞팔로우
                                      </button>
                                    )}
                                  </div>
                                );
                              })}
)
}

[components/FollowingModal.js]

const FollowingModal = ({ setFollowingModal, followingsInfo }) => {
  const dispatch = useDispatch();
  
    const onClickUnFollow = (id) => () => {
    dispatch(unfollowRequest(id));
  };
  
  return (
  <div className="mt-3 w-96 p-4 border rounded-lg shadow-md">
                        <div className="flex items-center justify-between mb-4">
                          <h5 className="text-xl font-bold leading-none text-gray-900">
                            팔로잉 수 : {followingsInfo.length}
                          </h5>
                          <a
                            href="#"
                            className="text-sm font-medium text-blue-600 hover:underline dark:text-blue-500"
                          >
                            View all
                          </a>
                        </div>
                        <div className="flow-root">
                          <ul
                            role="list"
                            className="divide-y divide-gray-200 dark:divide-gray-700"
                          >
                            <li className="py-3">
                              {followingsInfo.map((following) => {
                                return (
                                  <div className="flex items-center space-x-4">
                                    <div className="flex-shrink-0">
                                      <img
                                        className="ml-2 w-8 h-8 rounded-full"
                                        src="/docs/images/people/profile-picture-1.jpg"
                                        alt="Neil image"
                                      />
                                    </div>
                                    <div className="flex-1 min-w-0">
                                      <p className="text-sm font-medium text-gray-900 truncate">
                                        {following.nickname}
                                      </p>
                                      <p className="text-sm text-gray-500 truncate dark:text-gray-400">
                                        {following.email}
                                      </p>
                                    </div>
                                    <button
                                      onClick={onClickUnFollow(following.id)}
                                      className="bg-red-500 text-white hover:bg-light-beige hover:text-red-500 rounded inline-flex items-center text-base font-semibold text-gray-900"
                                    >
                                      언팔로우
                                    </button>
                                  </div>
                                );
                              })}
                            </li>
                          </ul>
                        </div>
                      </div>
                      )

[redux-saga]

function followAPI(data) {
  return axios.patch(`/user/${data}/follow`);
}

function* follow(action) {
  try {
    const data = action.payload;
    console.log("data", data);
    const result = yield call(followAPI, data);
    yield put(followSuccess(result.data));
  } catch (error) {
    yield put(followFailure(error));
    console.log(error);
  }
}

function unfollowAPI(data) {
  return axios.delete(`/user/${data}/follow`);
}

function* unfollow(action) {
  try {
    const data = action.payload;
    const result = yield call(unfollowAPI, data);
    yield put(unfollowSuccess(result.data));
  } catch (error) {
    yield put(unfollowFailure(error));
    console.log(error);
  }
}

[redux-toolkit]

 followSuccess: (state, action) => {
      const data = action.payload;
      state.followLoading = false;
      state.followComplete = true;
      state.me.Followings.push({ id: data.UserId });
    },
 unfollowSuccess: (state, action) => {
      const data = action.payload;
      state.unfollowLoading = false;
      state.unfollowComplete = true;
      state.me.Followings = state.me.Followings.filter(
        (v) => v.id !== data.UserId
      );
    },

[routes/user.js]

router.patch("/:userId/follow", isLoggedIn, async (req, res, next) => {
  // PATCH /user/1/follow
  try {
    const user = await User.findOne({ where: { id: req.params.userId } });
    if (!user) {
      res.status(403).send("없는 사람을 팔로우하려고 하시네요?");
    }
    await user.addFollowers(req.user.id);
    res.status(200).json({ UserId: parseInt(req.params.userId, 10) });
  } catch (error) {
    console.error(error);
    next(error);
  }
});

router.delete("/:userId/follow", isLoggedIn, async (req, res, next) => {
  // DELETE /user/1/follow
  try {
    const user = await User.findOne({ where: { id: req.params.userId } });
    if (!user) {
      res.status(403).send("없는 사람을 언팔로우하려고 하시네요?");
    }
    await user.removeFollowers(req.user.id);
    res.status(200).json({ UserId: parseInt(req.params.userId, 10) });
  } catch (error) {
    console.error(error);
    next(error);
  }
});
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글