简体   繁体   中英

The Modal body not render the component in html after button click

I am new to react. I try to use the button onClick to call function for render the component in html.

After execution, does not appear on the page. Like this: https://imgur.com/a/jnPwEGN

But when I check the html element (F12), the react-c3js element is contains the element, and then it suddenly appears in the screen, like this: https://imgur.com/a/qHbv1zq

But if I don't look at it and wait, the chart will never appear.

This is my .js file

// draw the Chart in html
function drawHistoryChart(data) {
    console.log("data: ", data);
    const data2 = {
        columns: [
            ['data1', 30, 200, 100, 400, 150, 250],
            ['data2', 50, 20, 10, 40, 15, 25]
        ]
    };
    ReactDOM.render(<C3Chart data={data2} />, document.getElementById('react-c3js'));
}

//
class CarPark extends React.Component {
    static defaultProps = {
        parkId: "Not Found Id",
        parkName: "Not Found Name",
        address: "Not Found Address",
        totalSpace: 0,
        surplusSpace: 0,
        payGuide: "Not Found Pay Guide",
    };
    static propTypes = {
        parkId: PropTypes.string.isRequired,
        parkName: PropTypes.string.isRequired,
        address: PropTypes.string.isRequired,
        totalSpace: PropTypes.number.isRequired,
        surplusSpace: PropTypes.string.isRequired,
        payGuide: PropTypes.string.isRequired,
    };

    // Fetch data and pass data to drawHistoryChart Function
    requestHistoryOfCarPark(parkId, week, time) {
        fetch("/findHistoryByCarPark?place=" + parkId + "&week=" + week + "&time=" + time)
            .then((response) => {
                return response.json();
            }).then((jsonData) => {
                drawHistoryChart(jsonData);
            }).catch((err) => {
                console.log('error: ', err);
            });
    }

    render() {
        return (
            <div className="card">
                <div className="card-header">
                    <button className="btn" data-toggle="modal" data-target="#myModal" onClick={() => this.requestHistoryOfCarPark(this.props.parkId, getWeek(), getTime())}><i className='fas fa-search' style={style}></i></button>
                    {this.props.parkId}-{this.props.parkName}
                </div>
                <div className="card-body">
                    <div>地址:{this.props.address}</div>
                    <div>總車位:{this.props.totalSpace}</div>
                    <div>剩餘車位:{this.props.surplusSpace}</div>
                    <div>價錢資訊:{this.props.payGuide}</div>
                </div>
            </div >
        )
    }
}

and this is my html

<div class="modal fade" id="myModal">
    <div class="modal-dialog modal-xl">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Modal Heading</h4>
          <button type="button" class="close" data-dismiss="modal">&times;</button>
        </div>

        <div class="modal-body">
          <div id="react-c3js"></div>
        </div>

        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

Has anyone encountered this problem? Very grateful for any help!

Problem

Your code isn't working because you are not handling the Javascript for the toggling of the Modal correctly. React is a Javascript library, if you are using it take full advantage of it.

You do not need to pass data-toggle attributes in your HTML. You don't want to use straight up HTML like that if you are using React. You want to create a Modal functional component and use JSX. Convert your modal HTML into a React functional component that accepts isOpen and has a onClose method.

Solution

There isn't a one size fits all solution to your issue here. You can approach this in a couple ways. You could create a Modal component on tap on the shoulders of a library to do the heavy lifting for you. I strongly recommend the latter since you are new. Then play around with building your own component yourself.

Two libraries that are popular with React are Material UI or Reactstrap .

You can read up on Material UI here: https://material-ui.com/ . And Reactstrap here: https://reactstrap.github.io/

These libraries have a ton of Bootstrap goodies that you can play around with in your application.

Here's an example of how you could use Reactstrap in you component to get started.

Reactstrap: Modals

Add Reactstrap to your project. Using npm: npm i reactstrap react-dom or using yarn: yarn add reactstrap react-dom . I assume you have bootstrap installed as well since you are using the bootstrap classes. You should be good to go to start using reactstrap at this point.

Updating CarPark Component

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

class CarPark extends Component {
   const [isOpen, setIsOpen] = useState(false) //creating a state variable isOpen whose default value is false

  //fetch your data method

   //function for toggling the modal, accepts no params
   //ES6 notation, the arrow function
   const toggleModal = () => {
     setIsOpen(!isOpen); //setting state equivalent to this.setState({ isOpen: !this.state.isOpen })
   }; 

   //function for opening the modal and calling requestHistoryOfCarPark
   const handleOpenModal = () => {
     const { parkId } = this.props; //destructuring props so you don't have to right this.props.parkId everywhere you can just call parkId
     this.requestHistoryOfCarPark(parkId, getWeek(), getTime());
     setIsOpen(true); //whenever the button is clicked always open the modal
   }; 

   render() {
     const { address, parkId, parkName, payGuide, surplusSpace, totalSpace } = this.props //destructuring props again

     return(
      //this <> empty tag is a Fragment
      <>
       <Card>
        <CardHeader>
          <Button onClick={handleOpenModal}><i className='fas fa-search' style={style}></i></Button>
          { parkId } - { parkName }
        </CardHeader>
        <CardBody>
          <div>{ address } </div>
          <div> { totalSpace } </div>
          <div> { surplusSpace } </div>
          <div> { payGuide } </div>
        </CardBody>
       </Card>
       //Put your modal under the component where you want to access it
       <Modal isOpen={isOpen} toggle={toggleModal}>
        <ModalHeader tag='h4'> Modal Heading </ModalHeader>
        <ModalBody><div id="react-c3js"></div></ModalBody>
        <ModalFooter>
          <Button color='secondary' onClick={toggleModal}>Close</Button>
        </ModalFooter>
       </Modal>
     </> 
    )
}

}

Fragments I wrapped the Card and Modal inside of a Fragment you could just as easily use a <div></div> but fragments allow you to have sibling components without needing to wrap in an HTML parent ie <div> . You can read up on Fragments here .

Suggestion

I know getting into a new framework is exciting and you just want to dive right in, but I highly recommend reading through the React documentation (which can be daunting) and doing some tutorials or reading walkthrough guides.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM