Actualmente estoy tratando de hacer modales en React y quiero hacer una cuadrícula donde "botón 1" muestra "modal 1" y "botón 2" muestra "modal 2", etc. En el momento en que presiono mi botón para mostrar un modal, muestra ambos modal 1 y modal 2. ¿Cómo lo configuro para que el botón 1 solo abra modal 1?

Esta es mi App.js:

import React from 'react';
import './main.css';
import Modal from './components/Modal/modal';

class App extends React.Component {
  state = {
    show: false
  };

  showModal = x => {
    this.setState({
      show: !this.state.show
    });
  };

  render() {
    return (
      <div>
        <div className="button-container">
          <button className="toggle-button" onClick={x => {
            this.showModal(x);
          }}>Show yourself Modal!</button>
        </div>
        <Modal onClose={this.showModal} show={this.state.show} title="Test modal 1" id="1">Lorem ipsum</Modal>
        <Modal onClose={this.showModal} show={this.state.show} title="Test modal 2" id="2">I am a different modal</Modal>
      </div>
    );
  }
}

export default App;

Y este es mi componente modal.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './modal.css';

export default class Modal extends Component {
    onClose = x => {
        this.props.onClose && this.props.onClose(x);
    };

    render() {
        if(!this.props.show) {
            return null;
        }

        return (
            <div className="modal-wrapper">
                <h2 className="modal-header">{this.props.title}</h2>
                <div>{this.props.children}</div>
                <div>
                    <button className="modal-close" onClick={this.onClose}></button>
                </div>
            </div>
        )
    }
}

Modal.propTypes = {
    onClose: PropTypes.func.isRequired,
    show: PropTypes.bool.isRequired
};
1
Joachim 28 oct. 2019 a las 16:13

3 respuestas

La mejor respuesta

La forma más sencilla sería agregar una segunda clave a su estado para que pueda administrar mostrar ambos modales de forma independiente.

class App extends React.Component {
  state = {
    show1: false,
    show2: false
  };

Luego, haga que su función de cambio sea una función currificada que acepte un parámetro para actualizar la parte correcta del estado. Para usar una variable para acceder a una clave de objeto, necesitamos acceder a ella como una matriz como esta:

  showModal = (modal) => (e) => {
    this.setState({
      [modal]: !this.state[modal]
    });
  };

Entonces úsalo así:

  render() {
    return (
      <div>
        <div className="button-container">
          <button className="toggle-button" onClick={this.showModal('show1')}>Show yourself Modal 1!</button>
          <button className="toggle-button" onClick={this.showModal('show2')}>Show yourself Modal 2!</button>
        </div>
        <Modal onClose={this.showModal('show1')} show={this.state.show1} title="Test modal 1" id="1">Lorem ipsum</Modal>
        <Modal onClose={this.showModal('show2')} show={this.state.show2} title="Test modal 2" id="2">I am a different modal</Modal>
      </div>
    );
  }
}
2
Brian Thompson 28 oct. 2019 a las 13:26

Si necesita Button para cada Modal y controla su comportamiento con él, puede introducir un estado en el componente modal haciendo algo como esto:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './modal.css';

export default class Modal extends Component {
    constructor(props) {
       super(props);
       this.state = {
         showModal: false,
       }
    }   

    toggleShow = () => {
        const { showModal } = this.state;
        this.setState({showModal: !showModal})
    };

    render() {
        const { showModal } = this.state;        
        return (
            <div className="modal-wrapper">
                { showModal &&
                <div>
                    <h2 className="modal-header">{this.props.title}</h2>
                    <div>{this.props.children}</div>
                </div>
                }
                <div>
                    <button className="modal-close" onClick={() => this.toggleShow()}>{this.props.btnText}</button>
                </div>
            </div>
        )
    }
}

Se puede construir más para alterar el comportamiento predeterminado . Esto debería limpiar su código App.js.

1
m.sohail 28 oct. 2019 a las 14:17

Por el momento no tiene nada en su estado que indique qué modal mostrar. Estás utilizando this.state.show para controlar la visibilidad de ambos modales.

Puede introducir una propiedad de estado en su componente App que se utiliza para elegir qué modal mostrar. Por ejemplo, pasar un modalId o similar a su controlador de clics. ( descargo de responsabilidad: sintaxis no probada, ¡pero el principal tiene razón!)

Entonces su estado puede verse así:

state = {
  [
    { 
      id: 1,
      show: false
    },
    { 
      id: 2,
      show: false
    },
  ]
}

Luego, en su controlador de clics, deberá pasar la identificación del modal para mostrar / ocultar. Debería determinar esto a partir de algo en su interfaz de usuario.

showModal(id) => {
  this.setState({
    [id]: !this.state[id].show
  })
}
1
dougajmcdonald 28 oct. 2019 a las 13:25