Skip to content
Advertisement

Mapped nested component doesn’t work peopetly (React Js)

I have a list of items mapped to be displayed on my “allItems” page. Now every Item has a button that fires up a modal with the specs of the item, but this modal display the same value for all the item (the last one in the array). I tried to pass the id in toggle func but it doesn’t work.

Anyone knows how can I display the same data in the Card and the Modal?

Here’s my code:

 state = {
        modal: false,
    }

    toggle = () => {
        this.setState({
            modal: !this.state.modal
        })
    }
 render(){
 return(
 {rooms.map(({ _id, name, descr, prezzo }) => (
                        <>
                        <Card key={_id} className="rooms-card-template">
                            <CardImg />
                            <CardBody>
                                <CardTitle>{name}</CardTitle>
                                <CardText>{descr}</CardText>
                                <CardSubtitle>{prezzo}$/notte</CardSubtitle>
                                <Button onClick={this.toggle}>Apri Annuncio</Button>
                                
                                <Modal isOpen={this.state.modal} toggle={this.toggle}>
                                    <ModalHeader >{name}</ModalHeader>
                                    <ModalBody>
                                        {descr}
                                        <h5 style={{ paddingTop: "10px"}}>Riepilogo prenotazione</h5>
                                        <Form>
                                            <FormGroup>
                                                <Label>Struttura:</Label>
                                                <Input value={name}/>
                                            </FormGroup>
                                            <FormGroup>
                                                <Label>Ospiti:</Label>
                                                <Input type="select"name="ospiti" id="ospiti">
                                                    <option>1</option>
                                                    <option>2</option>
                                                    <option>3</option>
                                                    <option>4</option>
                                                    <option>5</option>
                                                    <option>6</option>
                                                    <option>7</option>
                                                    <option>8</option>
                                                    <option>9</option>
                                                </Input>
                                            </FormGroup>
                                            <FormGroup>
                                                <Label>Check in</Label>
                                                <Input type="date" name="checkin-date" id="checkin-date" placeholder="Check in" />
                                            </FormGroup>
                                            <FormGroup className="rooms-checkout">
                                                <Label>Check out</Label>
                                                <Input type="date" name="checkout-date" id="checkout-date" placeholder="Check out" /> 
                                            </FormGroup>
                                            { isAuth ? userAuth : userUnauth }
                                        </Form>
                                    </ModalBody>
                                </Modal>
                            </CardBody>
                        </Card>

                        </>
                    ))}
)
}

Advertisement

Answer

Issue

You’ve a single boolean modal state that all the modals cue from. When this.state.modal is true then a modal is rendered and opened for each element being mapped.

Solution

Instead of storing a boolean value for whether or not a modal should be open you should store an id when you want a specific modal to open.

state = {
  modal: null // <-- null, non-id state value
};

toggle = (id) => () => { // <-- curried function handler
  this.setState((prevState) => ({
    modal: prevState.modal === id ? null : id // <-- set new id or toggle off
  }));
};

render() {
  return (
    <>
      {rooms.map(({ _id, name, descr, prezzo }) => (
        <Card key={_id} className="rooms-card-template">
          ...
          <CardBody>
            ...
            <Button
              onClick={this.toggle(_id)} // <-- pass id
            >
              Apri Annuncio
            </Button>

            <Modal
              isOpen={this.state.modal === _id} // <-- open if id is match
              toggle={this.toggle(_id)} // <-- pass id
            >
              ...
            </Modal>
          </CardBody>
        </Card>
      ))}
    </>
  );
}
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement