Home > Back-end >  Conditionally changing a dynamically generated component in React
Conditionally changing a dynamically generated component in React

Time:05-11

I'm trying to change the 'follow' icon when clicked and unclicked, but I want it to change only for the current irritation of the map loop (for the current trip, and not for the others), but for some reason, it changes the icon of all the items (trips). how can I fix it so it will change for the current irritation only? thanks.

const Home = (props) => {
    const navigate = useNavigate();
    const [follow, setFollow] = useState(false);
    console.log("home-page")
    let trips = props.trips;

    const hadleFollowButton = (trip) => {
        setFollow(!follow)
        if (follow) trip.numOfFolowers  ;
        else trip.numOfFolowers--;

        fetch(`http://localhost:5000/api/trips/${trip.tripID}`,
            {
                method: 'PUT',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(trip)
            })
            .then(res => res.json())
            .then(data => {
                console.log('data posted:')
                console.log(data)
            })
            .catch(err => {
                console.log('err')
                console.log(err)
            })
    }


    let user = sessionStorage.getItem("user")
    let adminIsLoged = sessionStorage.getItem("adminPermissions")
    let userIsLoged = sessionStorage.getItem("isRegistered")

    //Redirects user who changed the URL while not loged-in
    if (!adminIsLoged && !userIsLoged) {
        navigate('/login');
    }

    return (
        <>
            <Box sx={{ flexGrow: 1 }}>
                <AppBar position="static">
                    <Toolbar variant="dense">
                        <CardTravelIcon />
                        <Typography
                            style={{ margin: 'auto' }}
                            variant="h6"
                            color="inherit"
                            component="div"
                        >
                            VACATION FINDER
                        </Typography>
                        <Typography
                            variant="h6"
                            color="inherit"
                            component="div"
                        >
                            Hello {user}!
                        </Typography>
                    </Toolbar>
                </AppBar>
            </Box>
            <div className='home-background' style={{ background: '#afcadb' }}>
                {/* <CardHeader>our trips</CardHeader> */}
                <Paper
                    style={{ background: '#8ebdaf' }}
                    elevation={10}
                    className='center'
                // variant='outlined'
                >

                    {/* <Stack direction="row" className='center'> */}
                    <Typography variant="h4" color="primary" component="div" style={{ background: '' }}>
                        our trips
                    </Typography>
                    {/* </Stack> */}
                </Paper>
                <Grid container>
                    {
                        trips.map((trip) => {
                            return (
                                <Grid item xs={12} sm={6} md={4} key={trip.tripID}
                                    id={`${trip.destination}trip-card`}
                                >
                                    <Card sx={{ maxWidth: 345, m: 2 }}>
                                        <CardMedia
                                            component="img"
                                            alt="error loading picture"
                                            height="140"
                                            image={require(`../uploads/${trip.destination}.jpg`)}
                                        />
                                        <CardContent>
                                            <Typography gutterBottom variant="h5" style={{ float: "left" }} component="div">
                                                {trip.destination}
                                            </Typography>
                                            <Typography variant="h5" color="secondary" style={{ float: "right" }}>
                                                {trip.date}
                                            </Typography>
                                            <br /><br />
                                            <Typography variant="body2" color="primary">
                                                {trip.description}
                                            </Typography>
                                        </CardContent>
                                        <CardActions>
                                            <IconButton
                                                size="large" color="inherit"
                                                onClick={() => hadleFollowButton(trip)}
                                            >
                                                <Badge badgeContent={trip.numOfFolowers} color="error">
                                                {/* problem here: */}

                                                    {follow ? < FavoriteIcon /> : < FavoriteBorderIcon />}
                                                </Badge>
                                            </IconButton>
                                        </CardActions>
                                    </Card>
                                </Grid>
                            )
                        })
                    }
                </Grid>

            </div >
        </>
    )
}

export default Home;

CodePudding user response:

This is happening because you have same follow state for all the trips. To fix this either have a follow in trip object itself or make a new component named Trip and check about follow there by doing this every trip object in trips array will have their own follow state. Something like:

const Trip = (props) =>{
  let {trip} = props;
  const [follow, setFollow] = useState(false);

  const hadleFollowButton = (trip) => {
    setFollow(!follow);
    if (follow) trip.numOfFolowers  ;
    else trip.numOfFolowers--;

    fetch(`http://localhost:5000/api/trips/${trip.tripID}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(trip),
    })
      .then((res) => res.json())
      .then((data) => {
        console.log("data posted:");
        console.log(data);
      })
      .catch((err) => {
        console.log("err");
        console.log(err);
      });
  };
  return(
    <Grid item xs={12} sm={6} md={4} key={trip.tripID} id={`${trip.destination}trip-card`}>
                <Card sx={{ maxWidth: 345, m: 2 }}>
                  <CardMedia component="img" alt="error loading picture" height="140" image={require(`../uploads/${trip.destination}.jpg`)} />
                  <CardContent>
                    <Typography gutterBottom variant="h5" style={{ float: "left" }} component="div">
                      {trip.destination}
                    </Typography>
                    <Typography variant="h5" color="secondary" style={{ float: "right" }}>
                      {trip.date}
                    </Typography>
                    <br />
                    <br />
                    <Typography variant="body2" color="primary">
                      {trip.description}
                    </Typography>
                  </CardContent>
                  <CardActions>
                    <IconButton size="large" color="inherit" onClick={() => hadleFollowButton(trip)}>
                      <Badge badgeContent={trip.numOfFolowers} color="error"> 

                        {follow ? <FavoriteIcon /> : <FavoriteBorderIcon />}
                      </Badge>
                    </IconButton>
                  </CardActions>
                </Card>
              </Grid>
  )
}

and after that render this Trip comoponent in your Home component like:

{trips.map((trip) => (
  <Trip key={trip.tripID} trip={trip} />
))}

CodePudding user response:

When you are changing state in a conditional way... always change the state after you handle everything else unless you are positive you would want to do it first, but I honestly can't think of a case in which you would.

  • Related