Модальное окно с React и Redux

#reactjs #redux #react-redux

Вопрос:

Я сделал модальное окно с React и Redux. Я хотел избежать локального состояния, поэтому использовал Redux, чтобы сохранить информацию о том, открыт модал или нет.

Modal.js

 import React from 'react';
import './Modal.css';
import {useSelector, useDispatch} from 'react-redux';
import { isModalOpen } from '../actions/index';

const Modal = (props) => {
    const dispatch = useDispatch();
    const modalOpen = useSelector(state => state.isModalOpen);

    const closeModal = () => {
        dispatch(isModalOpen(false));
    }
    if(!modalOpen) return null;
    
    return(
        <div id="modal-container" onClick={closeModal}>
            <div id="modal">
                <span onClick={closeModal}>Close</span>
                <h2>Modal</h2>
                <p>description</p>
                {props.children}
            </div>
        </div>
    );
}

export default Modal;
 

App.js

 import React from 'react';
import { useDispatch} from 'react-redux';
import Modal from './Modals/Modal';
import Contents1 from './Modals/Contents1';
import Contents2 from './Modals/Contents2';
import { isModalOpen } from './actions/index';

import './App.css';

const App =  () => {

  const dispatch = useDispatch();

  const openModal1 = () => {
    dispatch(isModalOpen(true)); 
  };

  const openModal2 = () => {
    dispatch(isModalOpen(true));
  };

  return (
    <div>
      <button onClick={openModal1}>Open Modal 1</button>     
      <Modal>
        <Contents1 />
      </Modal>

      <button onClick={openModal2}>Open Modal 2</button>
      <Modal>
        <Contents2 />
      </Modal>
    </div>
  );
}

export default App;
 

Когда у меня есть одна кнопка, открывающая один модальный режим, все в порядке. Однако, если я хочу, чтобы другая кнопка открывала модальное окно с другим содержанием2, это не работает.

Как изменить код, чтобы первая кнопка открывала Модал с Содержанием1, а вторая кнопка открывала Модал с Содержанием2?

Большое спасибо.

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

1. Что, если вы нажмете кнопку Open Modal 2 и затем Open Modal 1 ? открывает ли он 2-й, а дозент открывает 1-й? Если это так, это может быть просто государственная вещь. Вы не сбрасываете состояние redux из true ti false при закрытии модального режима. Следовательно, отправка одного и того же значения не вызывает повторной отрисовки. Если это так, вам нужно запустить отправку, чтобы установить состояние false на модальное закрытие. Простой тест: console.log(isModalOpen ) внутри openModal1 и openModal2 до dispatch , чтобы проверить, является ли начальное состояние false или какое-то другое значение

2. Оба режима открываются при нажатии любой из кнопок. Модальности перекрывают друг друга, и та, что с Содержанием2, находится сверху.

Ответ №1:

Почему вы избегали использования местного штата?? Поскольку оба модала используются внутри этого компонента, гораздо разумнее использовать локальное состояние, чем хранить его в глобальном состоянии. Это также делает код короче и чище IMO.

 const App =  () => {
  const [currentModal, setCurrentModal] = useState(null);

  return (
    <div>
      <button onClick={() => setCurrentModal('modal1')}>Open Modal 1</button>     

      <button onClick={() => setCurrentModal('modal2')}>Open Modal 2</button>
      {currentModal ? (
        <Modal handleModalClose={() => setCurrentModal(null)}>
           {currentModal === "modal1" ? <Contents1 /> : <Contents2 />}
        </Modal>
      )}
    </div>
  );
}

export default App;
 

И тогда modal.js файл также будет упрощен

     const Modal = props => (
        <div id="modal-container" onClick={props.handleModalClose}>
            <div id="modal">
                <span onClick={props.handleModalClose}>Close</span>
                <h2>Modal</h2>
                <p>description</p>
                {props.children}
            </div>
        </div>
     );

     export default Modal;
 

Если вы все еще хотите использовать redux, вам следует сохранить имя модала вместо простого флага open и иметь сопоставление между именами модалов и компонентами

 import modals from '../utils/modals'
const Modal = (props) => {
    const dispatch = useDispatch();
    const currentModal = useSelector(state => state.currentModal);

    if(!currentModal) return null;
    
    return(
        <div id="modal-container" onClick={closeModal}>
            <div id="modal">
                <span onClick={closeModal}>Close</span>
                <h2>Modal</h2>
                <p>description</p>
                {modals[currentModal}
            </div>
        </div>
    );
}

export default Modal;
 

И modals.js экспортировал бы такой объект, как этот

 export default modals = {
    modal1: <ModalContent1 />,
    ...
}
 

Ответ №2:

В состоянии Redux вам нужно будет обрабатывать несколько модалов с помощью некоторого уникального идентификатора, в противном случае вы указываете, что любой модал должен быть открыт. Затем передайте «идентификатор» в вашей функции отправки.

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

1. Большое вам спасибо за вашу помощь, ребята. Я просто хотел иметь модальный фрейм «Модальный» и включать в него различное содержимое. И я хотел знать в каждый момент, открыт ли этот модал, установив флаг в магазине Redux. Похоже, он работает только с одним модальным для каждого компонента.