-
Social Media 만들기 - 8) follow, unfollow 기능 만들기NODE.JS 2021. 7. 10. 04:57
프로필 창에 나오는 follow 버튼을 활성화 시키자.
profile.js
{loading&& <Loading></Loading>} {error && <Alert variant="danger">{error}</Alert>} <div className="info"> <div className="info_container" key={user?._id}> <Avatar src={user?.avatar} size="supper-avatar" /> <div className="info_content"> <div className="info_content_title"> <h2>{user?.username}</h2> { user?._id === userInfo.user._id ? <button className="btn btn-outline-info" onClick={()=>setOnEdit(true)}>Edit Profile</button> : <FollowBtn user={user}/> } </div>
component>FollowBtn.js
import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { followUserProfile, unfollowUserProfile } from '../_actions/profileActions' function FollowBtn({user}) { const [follow, setFollow] = useState(false) const userLogin = useSelector(state => state.userLogin) const {userInfo} =userLogin const dispatch = useDispatch() useEffect(() => { if(userInfo.user.following.find(x=>x._id ===userId)){setFollow(true)} }, [userInfo.user.following, userId]) const handleFollow= async ()=>{ setFollow(true) await dispatch(followUserProfile(user)) } const handleUnfollow = async () =>{ setFollow(false) await dispatch(unfollowUserProfile(user)) } return ( <> { follow ?<button className="btn btn-outline-danger" onClick={handleUnfollow} >UnFollow</button> :<button className="btn btn-outline-info"onClick={handleFollow} >Follow</button> } </> ) } export default FollowBtn
라우터를 만들어주자.
userRouter.patch('/:id/follow', auth, async(req, res)=>{ try{ // const user = await User.findOne(req.params.id) // const follower = user.followers.filter(x=>x._id===req.user._id) // if(follower.length>0) return res.status(500).json({msg: "You followed this user."}) const user = await User.find({_id: req.params.id, 'followers':req.body._id}) if(user.length > 0) return res.status(500).json({msg: "You followed this user."}) const newUser = await User.findOneAndUpdate({_id: req.body._id}, { $push: {following: req.params.id} }, {new: true}).populate("followers following", "-password") await User.findOneAndUpdate({_id: req.params.id}, { $push: {'followers':req.body} }, {new: true}) res.send({ user : newUser, token:generateToken(newUser) }) } catch (err) { return res.status(500).json({msg: err.message}) } }) userRouter.patch('/:id/unfollow', auth, async(req, res)=>{ try{ const newUser = await User.findOneAndUpdate({_id: req.body._id}, { $pull: {following: req.params.id} }, {new: true}).populate("followers following", "-password") await User.findOneAndUpdate({_id:req.params.id}, { $pull:{'followers':req.body._id} }, {new:true}) console.log(newUser) res.json({ user:newUser, token:generateToken(newUser) }) }catch(err){ return res.status(500).json({message:err.message}) } })
여기서 그대로 following이나 follower로 넣으면 objectId 가 아니라고 해서 한참 해맸다. ㅠㅠ
https://stackoverflow.com/questions/26453507/argument-passed-in-must-be-a-single-string-of-12-bytes
이걸 보고 따라해서 'following'이러한 식으로 하니까 작동했다.
4시간은 고민한 것 같은데 그래도 작동해서 아슬아슬하지만 다행이다.
profile.action
export const followUserProfile = (user)=> async(dispatch, getState)=>{ const {userLogin: {userInfo}} = getState() let newUser = {...user, followers:[...user.followers, userInfo.user] } try{ const {data} = await axios.patch(`/api/users/${user._id}/follow`,userInfo.user,{ headers:{authorization:`Bearer ${userInfo?.token}`} } ) dispatch({ type:USER_FOLLOW_PROFILE, payload:newUser }) dispatch({ type:USER_LOGIN_SUCCESS, payload:data }) dispatch({ type:USER_UPDATE_PROFILE_SUCCESS, payload : data }) localStorage.removeItem('userInfo') localStorage.setItem('userInfo',JSON.stringify(data)) }catch(err){ dispatch({ type:ALERT, payload:{error:err.response && err.response.data.message? err.response.data.message : err.message} }) } } export const unfollowUserProfile = (user)=> async(dispatch, getState)=>{ const {userLogin: {userInfo}} = getState() let newUser = {...user, followers:user.followers.filter(x=>x._id !==userInfo.user._id) } try{ const {data} = await axios.patch(`/api/users/${user._id}/unfollow`,userInfo.user,{ headers:{authorization:`Bearer ${userInfo?.token}`} } ) dispatch({ type:USER_UNFOLLOW_PROFILE, payload:newUser }) dispatch({ type:USER_LOGIN_SUCCESS, payload:data }) dispatch({ type:USER_UPDATE_PROFILE_SUCCESS, payload : data }) localStorage.removeItem('userInfo') localStorage.setItem('userInfo',JSON.stringify(data)) }catch(err){ dispatch({ type:ALERT, payload:{error:err.response && err.response.data.message? err.response.data.message : err.message} }) } }
profilReducer.js
export const getUserProfileReducer = (state={}, action)=>{ switch(action.type){ case PROFILE_GETUSER_REQUEST: return {loading:true}; case PROFILE_GETUSER_SUCCESS: return {loading:false, user:action.payload} case PROFILE_GETUSER_FAIL: return {loading:false, error:action.payload} case PROFILE_GETUSER_RESET: return {loading:true} case USER_FOLLOW_PROFILE: return {...state, user:action.payload} case USER_UNFOLLOW_PROFILE: return {...state, user:action.payload} default: return state; } }
'NODE.JS' 카테고리의 다른 글
Social Media 만들기 - 9) following, followers 보여주기 (0) 2021.07.10 Cast to ObjectId failed for value "" at path "_id" 오류 (0) 2021.07.10 Social Media 만들기 - 7) userInfoProfile , edit profile 기능 만들기 (0) 2021.07.07 Social Media 만들기 - 6) search 기능 만들기 (Header) (0) 2021.07.06 Social Media 만들기 - 5) logout 기능 만들기 (Header) (0) 2021.07.06