Implement follow and unfollow button in React.js

Tags: , , , ,



I’m trying to implement a follow and unfollow button in my app.

I’ve been trying to update it in the state, but when I click the follow button it changes all the user’s buttons (not only the one clicked).

Now I’m a bit confused on how to show unfollow button if the user is already following the other user and make it work when clicked.

Here is my code:

class Followers extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      users: [],
      follower: [],
      following: [],
      button: "Follow"
    }
  }

  componentDidMount = () => {
    this.getUsers()
  }

  getUsers = () => {
    axios(`http://localhost:7001/api/users`)
      .then(response => {
        this.setState({ users: response.data})
        console.log(response.data)
      })
      .catch(error => {
        this.setState({ error: true })
      })
  }

  followUser = (e) => {
    e.preventDefault();
    const userId = this.props.user[0].id
    const followedId = e.target.value
    
    axios.post(`http://localhost:7001/api/users/${userId}/follow/${followedId}`, {
      userId,
      followedId,
      createdAt: new Date().toISOString().slice(0, 10),
      updatedAt: new Date().toISOString().slice(0, 10)
    })
    .then(response => {
      console.log(response.data)
      this.setState(state => ({
        button: "Unfollow",
        loggedIn: !state.loggedIn
      }))
    })
    .catch(error => {
      console.log(error)
    })
  }

  unfollowUser = (e) => {
    e.preventDefault();
    const userId = this.props.user[0].id
    const followedId = e.target.value

    axios.delete(`http://localhost:7001/api/users/${userId}/unfollow/${followedId}`)
    .then(response => {
      console.log(response)
      this.setState({ button: "Follow" })
    })
    .catch(error => {
      this.setState({ error: true })
    })
  }


  render() {
    const { users, button } = this.state
    const userId = this.props.user[0].id

    return (
      <div>
        <h2>Users in Unax</h2>
        <ul>
          {users.map((user, index) => {
           if(user.id !== userId) {
             return (
              <Card className="users" key= {index}>
                <CardBody>
                  <CardTitle>{user.user_name}</CardTitle>
                  <Button id="btn" value={user.id} onClick={this.followUser}>Follow</Button>
                  <Button id="btn" value={user.id} onClick={this.unfollowUser}>Unfollow</Button>
                </CardBody>
              </Card>
             )}  
          })}
        </ul>
      </div>
    )
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

My last try was to add two buttons and make a conditional, but I cannot think a way to compare if the relationship already exists, should this be done in the backend?

Answer

It looks as though all of your follow/unfollow buttons are linked to the same single piece of state, meaning that when its true they are all true and when false they are all false.

One way to achieve this is to have a ‘followed’ property in the user object. Then you can alter the button based on whether that user is already being followed or not.

You can then update the database and the local state to give the user the most responsive experience.

For example your user object could look something like:

{id: 1, name: Bob, followed: false, image: ....}

This would allow you to understand what state your button should be in.

In depth description of managing a friendship database



Source: stackoverflow