0

Hi I want to call reactstrap modal object programatically so that I can reuse it and call it depending on what the situation is. Currently I have it working by using props buy passing the modal state as a prop but I want to not have to manage the modal variable on the parent to make sure my code is a bit cleaner. Let me explain what I want to do:

Using the basic modal example in reactstrap I am removing the button since I will not be calling it when a button is clicked and want to create the modal object on the fly. This is what I have in mind...

/* Default simple reactstrap modal without button */        
/*  eslint react/no-multi-comp: 0, react/prop-types: 0 */

import React, { useState } from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';

const ModalExample = (props) => {
  const {
    buttonLabel,
    className
  } = props;

  const [modal, setModal] = useState(false);

  const toggle = () => setModal(!modal);

  const onModalLoad = () => { setModal(true); }

  return (
    <div>
      <Modal isOpen={modal} toggle={toggle} className={className} onOpened={onlLoad}>
        <ModalHeader toggle={toggle}>{props.title}</ModalHeader>
        <ModalBody>
          {props.body}
        </ModalBody>
        <ModalFooter>
          <Button color="secondary" onClick={toggle}>OK</Button>
        </ModalFooter>
      </Modal>
    </div>
  );
}

export default ModalExample;

Then I want to create the object on the fly by calling something like:

   const parentComponent = () => { 

const submitForm = event => {
   if (condition1) { 
      React.createElement( ModalExample, {title: 'issue1', 'this is the problem'} ); 
  }else if (condition2) { 
      React.createElement( ModalExample, {title: 'issue2', 'this is the problem'} ); 
  }else if (condition3) { 
      React.createElement( ModalExample, {title: 'issue3', 'this is the problem'} ); } 
  }
}

    return (
    <span >
   <Form onSubmit={submitForm}>
     <Button color="primary" type="submit">
         Submit
     </Button>
  </Form>
  </span> 
    )
}

This is somewhat similar to what is talked about on the link How to open/close react-bootstrap modal programmatically? but this option is not quite talked about and it is not working for me. Not sure what I am missing.

user1342645
  • 655
  • 3
  • 8
  • 13
  • Are you able to just control whether it is shown programatically in the parent? for example: ` const parentComponent = () => { const [showModal, setShowModal] = useState(false) return (
    {showModal && }
    ) }; `
    – PeteG Mar 04 '20 at 19:00
  • yes but in order to do that, I have the component defined in the parent with visibility set to false and keep track of the title, body,and visibility variables. Then I switch the visibility to true/false as I need to show/hide and control the text depending on what I want to display but I feel this is not a clean solution since I am handling the data and variables of the modal in the parent component. – user1342645 Mar 04 '20 at 19:07
  • If you want the modal to be reusable in different scenarios, assuming that might mean different title or body, then you will have to pass those details to it at some point. Even in your example where you create an element on the fly... you need to have the element defined in the place it is called, and you need to pass it things. – PeteG Mar 04 '20 at 19:10
  • I agree, which is why I am passing the props as {title: 'issue1', 'this is the problem'}, {title: 'issue2', 'this is the problem'},and {title: 'issue3', 'this is the problem'} which would fill out the title and body... – user1342645 Mar 04 '20 at 19:27

1 Answers1

0

Are you able to just control whether it is shown programatically in the parent? for example:

const parentComponent = () => {
  const [showModal, setShowModal] = useState(false)

return (
    <div>
        {showModal && <Modal title='my title text'  body='my title body'}/>}
        <button onClick={setShowModal(!showModal)}></button>
    </div>
      )
};

in your example you are only changing the title, so you can just store that in a variable... admittedly on the parent:

   const parentComponent = () => { 
let title;    
const submitForm = event => {

   if (condition1) title = 'issue1'; 
   else if (condition2) title = 'issue2';    
   else if (condition3) title = 'issue3'; 

  }
return (
{showModal && <Modal title={title}  body='my title body'}/>}
)
}

if you absolutely dont want to store a value on the parent you can have the full conditional in your return, but that seems messy to me (and really, it's the parent's return statement, so you arent taking the data out of the parent):

    return (
<div>
{condition1 && <Modal title='issue1'  body='my title body'}/>}
{condition2 && <Modal title='issue2'  body='my title body'}/>}
{condition3 && <Modal title='issue3'  body='my title body'}/>}
)

this assumes only one condition can be true - otherwise you could end up with three modals!

PeteG
  • 421
  • 3
  • 17
  • not sure i follow, can you build that example out and show me what would be in the conditions – PeteG Mar 04 '20 at 19:11
  • I edited the question but basically I don't want to have to keep track of showModal or any other variable in the parent component to make the other component independent. Also think about reusability, if I want to use the same modal component in different parent components, this would not be a very good way, or so I think. I am not sure if I am approaching the problem wrong, but feel free to comment. – user1342645 Mar 04 '20 at 19:24
  • So at some point you have to make the parent aware of the modal component. In your example you are trying to create an element of type 'ModalExample' - this isn't a built in element like a div so unless you tell the place you call it from what that is, then it won't know. There is also a lot of repeated code, calling create in each conditional. I'll update my answer to show another option – PeteG Mar 04 '20 at 19:26