Shh
Shh

Reputation: 309

React JS onClick change what is being rendered

The user enters and name and I map out a list of users based on the search criteria. The results are ordered by rank:

(resultsOrder = rank.map(id => results.get(id))

For each result the users pic, firstname and last name are displayed along with an Add Button (as only people who aren't friends are displayed). Once this button is pressed, the friendship is added to the database.

However onClick I also want the button to change from:

<Button name="Add" style="blue" onClick={() => addFriend(userId, r.user_id)} />    

to:

<p> - Request Sent - </p>

But I don't know how to change just one of the buttons in the map loop?

Example,

=> Search results are displayed:

Bob Smith ADD

Bob Smithies ADD

=> After Bob Smith is pressed:

Bob Smith - Request Sent -

Bob Smithies ADD


If this isn't easily possible: removing the specific result from the list after they have been added but displaying an alert("friend request sent") before would be acceptable.


rank: List(...)
  0: "3"
  1: "2"
  2: "1"
  3: "4"

results: Map(...)
   0: Array[2]
     0: "2"
     1: Record(...)
        0: Array[2]
           0: "user_id"
           1: "2"
        1: Array[2]
           0: "firstName"
           1: "Bob"
        2: Array[2]
           0: "lastName"
           1: "Smith"
   ...

class ShowResults extends Component {
  constructor(props) {
    super(props)
      this.state = {}
}

  render() {
    const { inviteFriend, results, rank, userId, addFriend } = this.props

    const resultsOrdered = rank.map(id => results.get(id))

    return (
      <div>
        <div>
          <table>
            <tbody>
              {resultsOrdered.map(
                (r, friendId) =>
                  (
                    <tr key={r.user_id}>
                      <td>
                        <img src={r.picUrl} />
                      </td>
                      <td>
                        {r.firstName} {r.lastName}
                      </td>
                       <Button name="Add" style="blue" onClick={() => addFriend(userId, r.user_id)} />
                    </tr>
                  )
               )}
            </tbody>
          </table>
        </div>
      </div>
      ) 
    }
  }

  export default ShowResults

Upvotes: 0

Views: 484

Answers (1)

Dev
Dev

Reputation: 3932

In handler, you can update your list to update the button text.

Based on my understanding, I have tried creating below snippet. Hope this helps.

const list = [
  {
    name: "Bob Smith",
    id:1
  },
  {
    name: "Martin Cooper",
    id:2
  },
  {
    name: "Bob Smithies",
    id:3
  },
  {
    name: "David",
    id:4
  }
];

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      list: list
    };
    this.addFriend = this.addFriend.bind(this);
  }
  
  some() {
    console.log("done:")
  }

  addFriend(item) {
    let updatedList = this.state.list.map(obj => {
       if(obj.id === item.id) {
         return Object.assign({}, obj, {
            updatedLabel: "Request Sent"
         });
       }
       return obj;
    });
    this.setState({
      list : updatedList
    }, () => {
      this.some()
    });
  }
  
  addFriendAndHide(item) {
    let updatedList = this.state.list.filter(obj => {
         if(obj.id === item.id) {
           return false;
         }
         return true;
      });
    this.setState({
      list : updatedList
    });
  }

  render() {
    return (
      <div>
        <table>
          <tbody>
            {this.state.list.map(item =>
              <tr key={item.itemId}>
                <td>
                  {item.name}
                </td>
                <td>
                  <button
                    className="delete"
                    onClick={() => this.addFriend(item)}
                  >
                    {item.updatedLabel || "Add"}
                  </button>
                </td>
                <td>
                  <button
                    className="delete"
                    onClick={() => this.addFriendAndHide(item)}
                  >
                    {"Hide after request is sent"}
                  </button>
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("app"));
table td {
     font-size: 14px;
     font-weight: normal;
     padding: 10px;
     border: 1px solid #eee;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Update:

Yes you can do call any fn after the state changes async as below:

this.setState({
  ...      //update label by updating list
}, ()=> {
   this.addFriend()
});

Upvotes: 1

Related Questions