0
votes

I am trying to dynamically display 3 buttons that each open a different modal. I'm struggling with finding the solution to open the modal that belongs to the button. I tried to implement it like the code below. It doesn't work which I expected but I"m struggling with finding the correct way of achieving the desired result.

button - modal code:

export default function SidenavButtons(props) {
    const [modalShow, setModalShow] = React.useState(false);

    return (
        <React.Fragment>

            <a class="dropdown-item" onClick={() => {setModalShow(true)}}>{props.usage}</a>
            {
                if(props.usage === "post" && modalShow){
                    <CreatePostModal
                    show={modalShow}
                    onHide={() => setModalShow(false)}
                    modelUsage={props.usage}
                />
                }
                if(props.usage === "tweet" && modalShow){
                    <CreateTweetModal
                    show={modalShow}
                    onHide={() => setModalShow(false)}
                    modelUsage={props.usage}
                />
                }
                if(props.usage === "tiktok" && modalShow){
                    <CreateTiktokModal
                    show={modalShow}
                    onHide={() => setModalShow(false)}
                    modelUsage={props.usage}
                />
                }
            }


        </React.Fragment>
    )
}
2

2 Answers

1
votes

Your mistake is using the if statement inside the return. You can just use the expression itself like the following

export default function SidenavButtons(props) {
    const [modalShow, setModalShow] = React.useState(false);

    return (
        <React.Fragment>

            <a class="dropdown-item" onClick={() => {setModalShow(true)}}>{props.usage}</a>
                {props.usage === "post" && modalShow &&
                    <CreatePostModal
                        show={modalShow}
                        onHide={() => setModalShow(false)}
                        modelUsage={props.usage}
                    />
                }
                {props.usage === "tweet" && modalShow &&
                    <CreateTweetModal
                        show={modalShow}
                        onHide={() => setModalShow(false)}
                        modelUsage={props.usage}
                    />
                }
                {props.usage === "tiktok" && modalShow &&
                    <CreateTiktokModal
                        show={modalShow}
                        onHide={() => setModalShow(false)}
                        modelUsage={props.usage}
                    />
                }
            }

        </React.Fragment>
    )
}
1
votes

What do you think about this:

export default function SidenavButton(props) {
    const [modalShow, setModalShow] = React.useState(false);

    return (
        <React.Fragment>
            <a class="dropdown-item" onClick={() => {setModalShow(true)}}>{props.usage}</a>
            {modalShow && (
              <Modal onHide={() => setModalShow(false)} show>
                {props.usage === 'post' && (
                  // Put here the content that would go inside CreatePostModal
                )}
                {props.usage === 'tweet' && (
                  // Put here the content that would go inside CreateTweetModal
                )}
                {props.usage === 'tiktok' && (
                  // Put here the content that would go inside CreateTiktokModal
                )}
              </Modal>
            )}
        </React.Fragment>
    )
}

And the Modal element would look something like this:

export default function Modal(props) {
  return <React.Fragment>
    {props.show && (
      <div className="modal-class-name">
        //Here I use props.children to render everything that is rendered inside 
        //the modal
        {props.children}
        <button onClick={props.onHide}>Close</button>
      </div>
    )}
  </React.Fragment>
}

I like this approach because it separates the concerns. There is a Modal component that handles showing stuff on a Modal and there is the SidenavButton component that uses Modal to render stuff in a modal depending on the usage.

Finally, just a quick reminder:

if(props.usage === "tiktok" && modalShow){
    <CreateTiktokModal
      show={modalShow}
      onHide={() => setModalShow(false)}
      modelUsage={props.usage}
    />
}

Will not render anything because you can only put values inside brackets, not actual javascript code, the correct implementation would be:

{
  (props.usage === "tiktok" && modalShow) && (
    <CreateTiktokModal
      show={modalShow}
      onHide={() => setModalShow(false)}
      modelUsage={props.usage}
    />
  )
}