1

I want to implement an authentication modal like Airbnb/Medium. When I click "Sign Up" in the Login Modal, The Login Modal closes and the Register Modal opens. I read react-modal docs and didn't see a way to do so. Could anyone please assist me finding a solution. Thanks.

H. Pham
  • 13
  • 2
  • 3
  • Hello, it would be nice to see some code of what you already have implemented. Aside from that i would suggest a container component where you can render those 2 modals based on the state (f.e. showLoginModal, showRegisterModal). You could set this by making use of a callback function in the onClick of your component. – Thibault Gobert Dec 04 '18 at 15:22

1 Answers1

10

I don't use React Modal, but I know a way of implementing it. The idea is to wrap your Sign Up and Login components inside a parent component that stores the modals' state and open/close methods. These methods can then be passed down as props to the children components.

Code example:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Modal from "react-modal";

class ModelWrapper extends Component {
  state = {
    loginOpened: false,
    signupOpened: false
  };
  openModal = modalType => () => {
    if (modalType === "login") {
      this.setState({
        loginOpened: true,
        signupOpened: false
      });
    } else if (modalType === "signup") {
      this.setState({
        loginOpened: false,
        signupOpened: true
      });
    }
  };
  closeModal = modalType => () => {
    if (modalType === "login") {
      this.setState({
        loginOpened: false
      });
    } else if (modalType === "signup") {
      this.setState({
        signupOpened: false
      });
    }
  };
  render() {
    const { loginOpened, signupOpened } = this.state;
    return (
      <>
        <Modal isOpen={loginOpened} onRequestClose={this.closeModal("login")}>
          <h1>Login</h1>
          <button onClick={this.openModal("signup")}>Open Signup</button>
          <button onClick={this.closeModal("login")}>Close this modal</button>
        </Modal>
        <Modal isOpen={signupOpened} onRequestClose={this.closeModal("signup")}>
          <h1>Sign Up</h1>
          <button onClick={this.openModal("login")}>Open Login</button>
          <button onClick={this.closeModal("signup")}>Close this modal</button>
        </Modal>
        <button onClick={this.openModal("login")}>Open Login</button>
        <button onClick={this.openModal("signup")}>Open Signup</button>
      </>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<ModelWrapper />, rootElement);

See it in action: https://codesandbox.io/s/q86lwklnxj

Brian Le
  • 2,646
  • 18
  • 28
  • Thank you. Does this also apply to multiple modals right? – H. Pham Dec 06 '18 at 04:51
  • It works however you need a better way of managing the state. If it helps please upvote and accept this answer. Thank you! – Brian Le Dec 06 '18 at 08:11
  • 1
    This answer seems to assume that you need to register any new modal in both openModal and closeModal methods. That's not a good idea. What if you have like 20? This breaks the SOLID open/close principle, btw. Sure, you could automate it and say "when a new one opens, loop over the rest of the modals and close them if needed". But still, you have to register any new modal in a list. – mayid Nov 08 '19 at 14:39
  • @mayid That's a good point. Haven't actually thought of a better solution yet, but a naive approach would be to use arrays and pass the modal index which can be used to set the state – Brian Le Nov 08 '19 at 20:02
  • I tried something today... assigning refs to modals, and storing them in a Map (using the reference as key, and the close method as a close value). Then, looping the Map and closing anything but the current modal. However, I got stuck. Now I'm trying with context, but I can't find a way to render ReactModal just once. – mayid Nov 08 '19 at 20:38
  • @mayid This is quite an old answer. A better solution would require a "master" component that manages an object of child modals. You can then choose a global state management library, such as Redux or React built in context to store the current active/open modal name, which can then be passed to this "master" component to conditionally render the appropriate child component (and of course close the rest) – Brian Le Feb 24 '21 at 15:27
  • Btw i did something with nextjs, so I created two forms on two pages and link it to each other , ie login page on signup and when I click signup it goes to signup link and the default state is set to open , so it just shows it , however not sure if its the right approach because technically i never closed the login modal – Naveen DINUSHKA Apr 01 '23 at 03:53