Reputation: 309
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
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