Passing props to modal in ReactJs

Millos picture Millos · Jan 8, 2019 · Viewed 8.8k times · Source

I work actually on my first react app. It's a collection app. On this app, there is an admin dashbord, with all items of the app, and admin user can delete or modify item (like a traditional e-commerce back office). For modify item, admin user click on button "Modify Item", and a modal open for modify item information.

My problem is when user open modal, the modal work fine, but i can't passing in props the information of the selected item (like brandname, reference, price ...). I'm very sorry to ask again a question in the same day, but i try many thing and no result. A little help is very welcome.

Thank you in advance,

This is my code:

import React, { Component } from 'react';
import { database } from '../firebase/firebase';
import * as firebase from 'firebase';
import withAuthorization from './withAuthorization';
import _ from 'lodash';
import AuthUserContext from './AuthUserContext';
import FileUploader from "react-firebase-file-uploader";
import Image from 'react-image-resizer';
import{InstantSearch, SearchBox, Hits, Highlight, RefinementList} from "react-instantsearch/dom";
import Modal from 'react-responsive-modal';



function removeToCatalogue(hit) { 
  const item = hit.objectID;
    firebase.database().ref(`catalogue/${item}`).remove();
    console.log("Capsule correctement supprimée du catalogue")
}




const Hit = ({hit, onEdit}) =>
    <div className="item">
       <img src={hit.avatarURL} width={150} height={150}></img>
        <h1 className="marque">{hit.marque}</h1>
        <h3 className="numero">{hit.numero}</h3>
        <h4 className="reference">{hit.reference}</h4>
        <h4 className="marquesuite">{hit.marquesuite}</h4>
        <p className="cote">{hit.cote}</p>
        <button className="btn btn-warning" onClick={onEdit}>Modify Item</button>
        <button className="btn btn-danger" onClick={() => removeToCatalogue(hit)}>Supprimer</button> 
    </div>

  const Content = ({ onEdit }) => {

    const EnhancedHit = props =>
       <Hit onEdit={ onEdit } { ...props } />

    return (
      <div className="text-center">  
        <Hits hitComponent={ EnhancedHit } />
      </div>
    )
  }




class Admin extends React.Component {
  constructor (props) {
    super (props);

    this.state = {
      marque: '',
      marquesuite: '',
      numero: '',
      reference: '',
      cote: '',
      avatar: "",
      isUploading: false,
      progress: 0,
      avatarURL: "",
      catalogue: {},
      showModal: false,

    };
    this.onInputChange = this.onInputChange.bind(this);
    this.onHandleSubmit = this.onHandleSubmit.bind(this);

  }


  onOpenModal = () => {
    this.setState({ open: true });
  };

  onCloseModal = () => {
    this.setState({ open: false });
  };


  onInputChange(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  onHandleSubmit(e){
    e.preventDefault();
    const catalogue = {
      marque: this.state.marque,
      marquesuite: this.state.marquesuite,
      numero: this.state.numero,
      reference: this.state.reference,
      cote: this.state.cote,
      avatar: this.state.avatar,
      avatarURL: this.state.avatarURL,

    };
    database.push(catalogue);
    this.setState({
      marque: '',
      marquesuite: '',
      numero: '',
      reference: '',
      cote: '',
      avatar: "",
      isUploading: false,
      progress: 0,
      avatarURL: "",
    });
  }

  handleUploadStart = () => this.setState({ isUploading: true, progress: 0 });
  handleProgress = progress => this.setState({ progress });
  handleUploadError = error => {
    this.setState({ isUploading: false });
    console.error(error);
  };

  handleUploadSuccess = filename => {
    this.setState({ avatar: filename, progress: 100, isUploading: false });
    firebase
      .storage()
      .ref("images")
      .child(filename)
      .getDownloadURL()
      .then(url => this.setState({ avatarURL: url }));
  };


  render (){
    const { open } = this.state;
    return (
      <div className="container-fluid">
        <div className="container">
        <h1 class="text-center">Espace d'Administration</h1>
        <a href="https://super-capsule.000webhostapp.com/signaler-modification" class="btn btn-primary btn-lg active" role="button" aria-disabled="true">Signaler une modification</a>
        <form onSubmit={this.onHandleSubmit}>
          <div className="form-group">
          <label>Marque de la capsule:</label>
          <input
            value={this.state.marque}
            type="text"
            name='marque'
            placeholder="Marque"
            onChange={this.onInputChange}
            ref="marque"
            className="form-control" />
          </div>
          <div>
          <label>Numéro de la capsule:</label>
          <input
            value={this.state.numero}
            type="text"
            name='numero'
            placeholder="Numéro de la capsule"
            onChange={this.onInputChange}
            ref="numero"
            className="form-control"/>
          </div>
          <div className="form-group">
          <label>Référence de la capsule:</label>
          <input
            value={this.state.marquesuite}
            type="text"
            name='marquesuite'
            placeholder="Référence de la capsule"
            onChange={this.onInputChange}
            ref="marquesuite"
            className="form-control"/>
          </div>
          <div className="form-group">
          <label>Référence de la capsule (suite):</label>
          <input
            value={this.state.reference}
            type="text"
            name='reference'
            placeholder="Référence de la capsule (suite)"
            onChange={this.onInputChange}
            ref="reference"
            className="form-control"/>
          </div>
          <div className="form-group">
          <label>Cote de la capsule:</label>
          <input
            value={this.state.cote}
            type="text"
            name='cote'
            placeholder="Cote de la capsule"
            onChange={this.onInputChange}
            ref="cote"
            className="form-control"/>
          </div>

          <label>Visuel de la capsule:</label>
          {this.state.isUploading && <p>Progress: {this.state.progress}</p>}
          {this.state.avatarURL && <img src={this.state.avatarURL} />}
          <FileUploader
            accept="image/*"
            name="avatar"
            randomizeFilename
            storageRef={firebase.storage().ref("images")}
            onUploadStart={this.handleUploadStart}
            onUploadError={this.handleUploadError}
            onUploadSuccess={this.handleUploadSuccess}
            onProgress={this.handleProgress}
          />
          <button className="btn btn-info">Ajouter une capsule</button>
        </form>
      </div>

        <h1 className="text-center">Catalogue de capsule</h1>



        <InstantSearch
            apiKey="xxx"
            appId="xxx"
            indexName="xxx">


            <SearchBox translations={{placeholder:'Rechercher une capsule'}} width="500 px"/>


            <Content onEdit={this.onOpenModal}/>  

              <div>
                <Modal open={open} onClose={this.onCloseModal} center>
                  <h2>Modification de la capsule</h2>
                  <p>Marque de la capsule:<input type="text" class="form-control" id="maj-marque" value=""></input></p>
                  <p>Numéro de la capsule:<input type="text" class="form-control" id="maj-num" value=""></input></p>
                  <p>Référence de la capsule:<input type="text" class="form-control" id="maj-ref" value=""></input></p>
                  <p>Référence de la capsule (suite):<input type="text" class="form-control" id="maj-refsuite" value=""></input></p>
                  <p>Cote de la capsule:<input type="text" class="form-control" id="maj-cote" value=""></input></p>
                  <button className="btn btn-success">Update</button>

                </Modal>
            </div>  


          </InstantSearch>



      </div>
    )
  }
}



const authCondition = (authUser) => !!authUser;

export default withAuthorization(authCondition)(Admin);

Answer

Claire Lin picture Claire Lin · Jan 9, 2019

You don't need to pass props to the Modal component. Instead, save whatever you want to display in the Admin state, and render it through there.

In the Hit component, onEdit function should take an argument which is an object with all the information you need in the modal. Where you had <button className="btn btn-warning" onClick={onEdit}>Modify Item</button> will become:

    handleClick = () => {
        // I simplified the data you need to be only marque and numero here and below.
        onEdit({marque: hit.marque, numero: hit.numero})
    }
    <button className="btn btn-warning" onClick={handleClick}>Modify Item</button>

Then in the Admin component:

    onOpenModal = (itemData) => {
        this.setState({ open: true, itemData  });
    };


    <Modal open={open} onClose={this.onCloseModal} center>
          <h2>Modification de la capsule</h2>
          <p>Marque de la capsule:<input type="text" class="form-control" id="maj-marque" value={this.state.itemData.marque}></input></p>
          <p>Numéro de la capsule:<input type="text" class="form-control" id="maj-num" value={this.state.itemData.numero}></input></p>
          <button className="btn btn-success">Update</button>
    </Modal>

Hope this helps. Let me know if you have any questions.