Shehan Silva
Shehan Silva

Reputation: 145

Using a function inside .map() in React , does not work properly

I tried using a function inside the map() function but yet it does not give the output required. I will explain the problem after these code sections.

map function code segment

 {bookings.map((booking) =>(
                            
                            <tr>
                                <th scope = "row">{number++}</th>
                                <td>{booking.tourId}</td>
                                <td>{booking.bookingDate}</td>
                                <td>{booking.arrivalDate}</td>
                                <td>{booking.country}</td>
                                <td>{GuideAssigned(booking.tourId)}</td>
                                <td><Button color="warning"  style = {{padding: "5px 5px 5px 5px" , width : "80px" , marginBottom : "8px"}}
                                onClick = {()=>{
                                    history.push(`/assign-guide/${booking.username}`);
                                }}
                                >Assign Guide</Button>
                               </td>
                            </tr>
    
                        ))}

The problem here is that the function gets called only for one tour ID , which is the first one in the table.The function does not get called for the other Tour ID's.Am I doing something wrong here?

Below is the function called

function GuideAssigned(tid){
        axios.get(`http://localhost:8070/assignedGuides/get/${tid}`).then((res)=>{
          console.log(res.data.guideId);
          setGuide(res.data.guideId);
          if (typeof guide == 'undefined'){
            return "Not Assigned";
          }
          
        }).catch((err)=>{
          console.log(err);
        })
        
        return guide;

        
    }

This works only for the first tour ID which gets passed as you can see below.(Guide Assigned field is same for all).

Table

Upvotes: 2

Views: 812

Answers (1)

Drew Reese
Drew Reese

Reputation: 203587

You can't call asynchronous code in the render of a React component. The reason they are all the same is likely because you've one guide state, set by setGuide(res.data.guideId);, and it's also very likely it's the last mapped element setting this value since it's the last to do a GET request.

You will want to make these GET requests when the bookings array reference updates. Use an useEffect hook for this.

const [guides, setGuides] = useState({});

useEffect(() => {
  bookings.forEach(({ tourId }) => {
    axios.get(`http://localhost:8070/assignedGuides/get/${tourId}`)
      .then(res => {
        setGuides(guides => ({
          ...guides,
          [tourId]: res.data.guideId,
        }));
      })
  });
}, [bookings]);

Use the mapped tourId to access the correct guides guideId value.

{bookings.map((booking) =>(
  <tr>
    ...
    <td>{guides[booking.tourId]}</td> // <-- access guide id by tour id
    ...
  </tr>
))}

Upvotes: 1

Related Questions