React — Modal открывается для каждого элемента в сопоставленном массиве, независимо от того, какой из них нажат

#reactjs #bootstrap-modal #react-functional-component

#reactjs #bootstrap-modal #реагирующий функциональный компонент

Вопрос:

Итак, я сопоставляю массив элементов и хочу открыть уникальный модальный для любого из них, на который нажат. По какой-то причине, если я нажимаю на любой из элементов, для каждого из элементов появляется модальный. Вот мой код

 const PrivateProjects = props => {
    const [show, setShow] = useState(false);

    const openModal = () => {
        setShow(true)
    }

    return (
        <div className='projectContainer'>
            {privateProjects.map((project, index) => (
                <div className='lightbox' onClick={() => {openModal()}}>
                    <div className='project'>
                        <h5>{project.name}</h5>
                        <img src={project.image} alt='hibiscus project' />
                    </div>
                    <MyModal title={project.name} img={project.image} show={show} onHide={()=> {setShow(null)}}/>
                </div>
            ))}
        </div>
    )
}

export default PrivateProjects;  

Вот мой модальный

 import React from 'react';
import Modal from 'react-bootstrap/Modal';
import {Button} from 'react-bootstrap';

const MyModal = (props) => {
    console.log(props);

    return (
      <Modal
        {...props}
        size="lg"
        aria-labelledby="contained-modal-title-vcenter"
        centered
      >
        <Modal.Header closeButton>
          <Modal.Title id="contained-modal-title-vcenter">
            {props.title}
          </Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <img src={props.img} />
          <p>
            Cras mattis consectetur purus sit amet fermentum. Cras justo odio,
            dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac
            consectetur ac, vestibulum at eros.
          </p>
        </Modal.Body>
        <Modal.Footer>
          <Button onClick={props.onHide}>Close</Button>
        </Modal.Footer>
      </Modal>
    );
  }

export default MyModal;  

Кроме того, кнопки для закрытия модала также не работают, работает только клавиша escape . Не уверен, где я с этим путаюсь.

PS Я убрал импорт и массив объектов для наглядности, потому что это много данных и работает нормально.

вот изображение того, что происходит с модальностями

Ответ №1:

Это потому, что все они используют одно и то же show состояние.

Приведенный ниже код аналогичен структуре, которая у вас есть после map выполнения:

 <MyModal title={project.name} img={...} show={show} />
<MyModal title={project.name} img={...} show={show} />
<MyModal title={project.name} img={...} show={show} />
  

Итак, когда show значение true, все они открываются.

Вы могли бы решить эту проблему, используя разные состояния для каждого из модалов.

Пример:

 const [show, setShow] = useState([false,false,false])

<MyModal title={project.name} img={...} show={show[0]} />
<MyModal title={project.name} img={...} show={show[1]} />
<MyModal title={project.name} img={...} show={show[2]} />

<button onClick={()=>setShow([false, false, true])}>Open Modal 3</button>
  

Комментарии:

1. Отлично. Я нашел решение, которое сопровождало ваш ответ, так что это было очень полезно. Большое вам спасибо! Отправит ответ сейчас

Ответ №2:

 const PrivateProjects = props => {
    const [show, setShow] = useState([false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]);

    const openModal = (index) => {
        handleChanges(index);
    }

    const handleChanges = (index) => {
            // 1. Make a shallow copy of the items
            let items = [show];
            // 2. Make a shallow copy of the item you want to mutate
            let item = items[index];
            // 3. Replace the property you're intested in
            item = true;
            // 4. Put it back into our array. N.B. we *are* mutating the array here, but that's why we made a copy first
            items[index] = item;
            // 5. Set the state to our new copy
            setShow(items);
    }

    return (
        <div className='projectContainer'>
            {privateProjects.map((project, index) => (
                <div className='lightbox' onClick={() => {openModal(index)}}>
                    <div className='project'>
                        <h5>{project.name}</h5>
                        <img src={project.image} alt='hibiscus project' />
                    </div>
                    <MyModal title={project.name} img={project.image} show={show[index]} onHide={()=> {setShow(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false)}}/>
                </div>
            ))}
        </div>
    )
}

export default PrivateProjects;  

Я чувствую, что может быть более простое решение, но это то, что заставило его работать для меня!