RFR Section 10 – Let Users Follow


React

Updated Mar 14th, 2022

Table of Contents

Course Summary

Chapter Details

Ch. 59 – Follow User Feature

Make sure you have a few users registered.

We want to keep track of who is following who in state by leveraging “useImmer” instead of React’s own “useState,” (import “useImmer” from “use-immer.”)

Early in the course, in “Profile.js” we created a piece of state related to a user’s profile and we have an “isFollowing” property. Cut the existing properties and get rid of “useState” line. Add a “useImmer” and paste back in clipboard. Add a few additional properties related to follow.

followActionLoading: false,
startFollowingRequestCount: 0,
StopFollowingRequestCoun: 0,
profileData: // {...this is the object we paste}

In the JSX look for an image tag and update the “src” attribute to be “state.profileData” and be sure to select and update all instances.

Make the follow button conditional and add an “onClick” set to “startFollowing” and “disabled,” set to “state.followActionLoading.”

{appState.loggedIn && !state.profileData.isFollowing && appState.user.username != state.profileData.profileUsername && state.profileData.profileUsername != "..." && (
  <button className="btn btn-primary">
    Follow<i className="fas fas-user-plus"></i>
  </button>
)}

Create “startFollowing” function and duplicate “useEffect” and have it watch for changes on the “startFollowingRequestCount” property.

useEffect(() => {

}, [startFollowingRequestCount])

Create another conditional button and function for the opposite case of “stopFollowing”

In “ProfilePosts.js” first “useEffect,” set dependency as the username in the URL.

Ch. 60 – Profile Followers and Following Tabs

To set up a secondary switch for followers/following tabs. Want each screen to have a shareable URL.

In “profile.js” import {navLink} from “react-router-dom.” Switch anchor tags to NavLinks and remove “active” class, (react-router-dom will handle this). Change “href” to “to.”

Import Switch and Route from “react-router-dom.” Add a switch and three routes one for “/:username,” “:followers,” “:following.”

Create new component called “ProfileFollowers” and copy all code from “ProfilePosts.js,” update to property for link. Do the same for “ProfileFollowing.”

In the map function tweak some settings and change hard-coded data for dynamic.

Render “ProfileFollowers” tag.

Create “ProfileFollowing” by coping from “ProfileFollwers” file and update and render this for the third route.

Extra credit to create new generic component and combine these two “following/followers” into one “follows” file since they are so similar.

Another extra credit is to do something for blank screens. “You don’t have any followers” or similar. Code in reference.

Ch. 61 – Homepage Post Feed

In “Home.js” file set up the state you need by importing “useImmer” from “use-immer.”

Set “useEffect” by borrowing from “Profile.js.”

Duplicate and tweak with empty array for dependency.

Update the “Axios.post()) URL to “/getHomeFeed”

Adjust state to be

setState((draft) => {
  draft.isLoading = false
  response.feed = response.data
})

Show loading icons at the appropriate time by importing “LoadingDotsIcon” component.

if (state.isLoading) {
  return <LoadingDotsIcon />
}

In the JSX cut the data return data from inside “Page” component.

{state.feed.length > && (
  <>
    <h2>The Latest from those you follow</h2>
    // Loop through feed here
  </>
)}
{state.feed.length == 0 && (
  <>
    <h2>Begin Following Someone</h2>
  </>
)}

Make sure “Axios” and “Link” is imported.

Bring in map function code from “Search.js” into “Home.js” and tweak to be “state.feed.map()”

Noticing a lot of duplicate code in the map function to get posts (now in three files: “Home,” “Search,” and “ProfilePosts”), so create reusable “Post.js” component and give it unique data as props. Import “Link” into “Post.js.” Copy and paste code from “Home.js” but first delete “onClick” property.

Update “Home.js” and “Search.js” and “ProfilePosts.js” to use this new “Post.js” component.

// in Home.js import the "Post.js" component

{state.feed.map(post => {
  return <Post post={post} key={post._id} />
})}

In “Search.js” give it another prop of “onClick” and include code that closes search.

// in Search.js import the "Post.js" component

{state.feed.map(post => {
  return <Post post={post} key={post._id} onClick={() => {appDispatch(type: 'closeSearch')}}/>
})}

Now in “Post.js,” on the opening “Link” tag, give it an “onClick” prop set to “props.onClick.”

Tweak some other code as well.

Also, in “Post.js” we don’t need a key, the outer component is providing a key for us.