0
votes

I'm new to React and have several cards that, when clicked, should open a modal however I don't know what to write in <Modal trigger={}>in my Modal component in order to get the Cards from the Card component. How would I link the modal to each card so that onClick of the card, the modal appears?

Home.js

class Home extends React.Component {
    constructor(props) {
      super(props) 
      this.state = { isEmptyState: true }
    }

    triggerOpenAlertState = () => {
      this.setState({
    ...this.state,
    isEmptyState: false,
    isOpenAlertState: true
      })
    }


  render() {
    return (
      <div>
        <i class="star outline icon big" id="favourites"></i>
        <GoogleAuth />
         <div>
      {this.state.isEmptyState && <Cards openAlert={this.triggerOpenAlertState} />}

      {this.state.isOpenAlertState && <ModalExample />}
    </div>
    </div>
    )
  }
}

Modal.js

const ModalExample = () => (
  <Modal trigger={}>
    <Modal.Header>Sign In</Modal.Header>
    <Modal.Content>
        <p>
        You must Sign In before you can add project ideas to your favourites.
        </p>
    </Modal.Content>
  </Modal>
)

export default ModalExample

Cards.js

const Cards = props => {
    return (
    <div class="row">
    <div class="column"><div onClick={props.openAlert} class="header card">Communication app for tenants/landlords</div></div> 
        <div class="column"><div onClick={props.openAlert} class="header card">Code Snippet Manager</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">Reservation Management System</div></div>
        <div class="column"> <div onClick={props.openAlert} class="header card">Budget Tracker</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">Caesar Cipher</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">Tax Calculator</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">Meme Generator</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">Virtual Interior Design app</div></div>
        <div class="column"><div onClick={props.openAlert} class="header card">App for the Elderly</div></div>
  </div>
1
could you please provide the parent component where you use Cards and ModalExample that would be easier for us to guide you.Palencar
In the render method of the parent with the cards you can try to display the modal if some card is selected. When you click on a card change cardsParent.state.selectedCard = someCard. When you close the modal cardsParent.state.selectedCard = null.Stefan
I've added the parent component (Home.js) to my question. @PalencarRahni

1 Answers

0
votes

Ok, so given your update you should proceed like so:

in your Home.js add a props "isOpen" that will be the visible state of the modal and if you need to get the cards object to your modal also add an object name "card" to your ModalExample component (and your state as empty object {}). link this props to isOpenAlertState and card. then update your function trigger open alert to get a param and save it to state

  triggerOpenAlertState = (card) => {
    this.setState({
      ...this.state, //this is not needed
     isEmptyState: false,
     isOpenAlertState: true,
     card: card;
    })
  }
...
...render() {
  return (
    <div>
      <i class="star outline icon big" id="favourites"></i>
      <GoogleAuth />
       <div>
    {this.state.isEmptyState && <Cards openAlert={this.triggerOpenAlertState} />}

     <ModalExample card={this.state.card} isOpen={this.state.isOpenAlertState}/>
  </div>
  </div>
  )
}

(if im not mistaken you don't need to test before adding your component modal.)

in your card update the onclick action to give the card object to the function:

 <div class="column"><div onClick={() => props.openAlert(clickedCardObject)} class="header card">Code Snippet Manager</div></div>

then in your Modal component get the props isOpen and card and link it in your trigger as you need :

  const ModalExample = ({isOpen, card}) => (
    <Modal trigger={isOpen}>
   // do Something with card values
  ...

That should do the trick to link your elements. Don't forget when you close your modal to set card state to null and isOpenAlertState to false.

I have some additional comments/tips about your code they are commonly called "good practice" for js.

_ First to increase the readability of your code you should use destructuring to get your vars i.e. (with your current code) :

render() {
    const {isOpenAlertState, isEmptyState} = this.state;
    return (
      <div>
        <i class="star outline icon big" id="favourites"></i>
        <GoogleAuth />
         <div>
      {isEmptyState && <Cards openAlert={this.triggerOpenAlertState} />}

      {isOpenAlertState && <ModalExample />}
    </div>
    </div>
    )
  }

this may not looks like much but it will greatly increase the readability of your code when you will have a lot of vars in state/ props.

_ Secondly you should use arrow fonction in your props/onClick. If you do not your functions will be instantly called on render and i doubt thats what you intend to do i.e:

Cards.js

 ...  <div class="column"><div onClick={() => props.openAlert()} class="header card">Code Snippet Manager</div></div> ...

Home.js

... {this.state.isEmptyState && <Cards openAlert={() => this.triggerOpenAlertState()} />} ...

Lastly, when you call setState({}) you don't need (but you can) to put ...this.state first as setState will automaticly get old states before putting new values or replace old values in it!

Hope this helps ! :D