Errors getting react-modal in my React Component - javascript

Sorry, React developer newbie. I am trying to use react-modal in my React Component based on the example here. I am getting a few errors I cannot figure out.
import React, {useState} from 'react';
import {
Card, Button, CardImg, CardTitle, CardText, CardGroup,
CardSubtitle, CardBody, CardFooter, CardHeader, CardColumns, CardDeck
} from 'reactstrap';
import Config from 'config';
import parse from 'html-react-parser';
import "./Item.css";
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)',
},
};
//Modal.setAppElement('FeaturedCards');
class FeaturedCards extends React.Component {
constructor() {
super();
this.state = {
name: 'React',
apiData: [],
};
}
async componentDidMount() {
const tokenString = sessionStorage.getItem("token");
const token = JSON.parse(tokenString);
let headers = new Headers({
"Accept": "application/json",
"Content-Type": "application/json",
'Authorization': 'Bearer ' + token.token
});
const response = await fetch(Config.apiUrl + `/api/Items/GetFeaturedItems`, {
method: "GET",
headers: headers
});
const json = await response.json();
console.log(json);
this.setState({ itemList: json });
}
render() {
const [modalIsOpen, setIsOpen] = useState(false);
const items = this.state.itemList;
let subtitle;
function handleClick(item) {
console.log('this is:', item);
setIsOpen(true);
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = '#f00';
}
function closeModal() {
setIsOpen(false);
}
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
return (
<div>
<CardColumns>
{items && items.map(item =>
<>
<Card key={item.itemNumber} tag="a" onClick={() => handleClick(item)} style={{ cursor: "pointer" }}>
<CardHeader tag="h3">Featured</CardHeader>
<CardImg top className="card-picture" src={"data:image/png;base64," + item.images[0]?.ImageData)} id={item.itemNumber + "Img"} alt={item.itemNumber} />
<CardBody className="card-body">
<CardTitle tag="h5">{item.itemNumber}</CardTitle>
<CardSubtitle tag="h6" className="mb-2 text-muted">{item.categoryName}</CardSubtitle>
<CardText className="card-description">{item.itemDescription}</CardText>
</CardBody>
<CardFooter className="text-muted">{formatter.format(item.price)}</CardFooter>
</Card>
<Modal
isOpen={modalIsOpen}
onAfterOpen={afterOpenModal}
onRequestClose={closeModal}
style={customStyles}
contentLabel="Example Modal">
<h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
<button onClick={closeModal}>close</button>
<div>I am a modal</div>
<form>
<input />
<button>tab navigation</button>
<button>stays</button>
<button>inside</button>
<button>the modal</button>
</form>
</Modal>
</>
)}
</CardColumns>
</div>
);
}
}
export default FeaturedCards;
I am getting a number of errors:
Where do I put const [modalIsOpen, setIsOpen] = useState(false) so I stop getting Error: Invalid hook call.?
What do I need to put in Modal.setAppElement('FeaturedCards'), because FeaturedCards does not work?
Any help will be appreciated.

After following #Nick and #DaveNewton comments...
...
Modal.setAppElement('#root');
...
class FeaturedCards extends React.Component {
constructor() {
super();
this.state = {
name: 'React',
apiData: [],
isOpen: false
};
}
...
render() {
const items = this.state.itemList;
let subtitle;
// This binding is necessary to make `this` work in the callback
handleClick = handleClick.bind(this);
closeModal = closeModal.bind(this);
function handleClick() {
this.setState({ isOpen: true });
}
function closeModal() {
console.log('Clicked close button')
this.setState({ isOpen: false });
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = '#f00';
}
...
return (
<div>
<CardColumns>
{items && items.map(item =>
<>
<Card key={item.itemNumber} tag="a" onClick={() => handleClick()} style={{ cursor: "pointer" }}>
<CardHeader tag="h3">Featured</CardHeader>
<CardImg top className="card-picture" src={"data:image/png;base64," + item.images[0]?.ImageData} id={item.itemNumber + "Img"} alt={item.itemNumber} />
<CardBody className="card-body">
<CardTitle tag="h5">{item.itemNumber}</CardTitle>
<CardSubtitle tag="h6" className="mb-2 text-muted">{item.categoryName}</CardSubtitle>
<CardText className="card-description">{item.itemDescription}</CardText>
</CardBody>
<CardFooter className="text-muted">{formatter.format(item.price)}</CardFooter>
</Card>
<Modal
isOpen={this.state.isOpen}
onAfterOpen={afterOpenModal}
onRequestClose={() => closeModal()}
style={customStyles}
contentLabel="Example Modal">
<h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
<button onClick={() => closeModal()}>close</button>
<div>I am a modal</div>
<form>
<input />
<button>tab navigation</button>
<button>stays</button>
<button>inside</button>
<button>the modal</button>
</form>
</Modal>
</>
)}
</CardColumns>
</div>
);
}
}
export default FeaturedCards;
... I got the modal to open and close.

Related

Context API is not Changing it's State at Global Level in React

This is My App.js File
import 'bootstrap/dist/css/bootstrap.min.css';
import Run from './Signupin/mainpage';
import Exp from './afterlogin/patirel/patmain';
import Exp1 from './afterlogin/adminrel/designdb';
import Exp2 from './afterlogin/adminrel/consult';
import Exp3 from './afterlogin/adminrel/support';
import Exp4 from './afterlogin/patirel/one';
import PostRequest from './afterlogin/adminrel/one';
import Docc from './afterlogin/docrel/one';
import {Routes,Route} from 'react-router-dom';
import Done from "./appointment/appointment";
import * as React from 'react';
function App() {
return (
<div>
<Routes>
<Route index element={<Run/>} />
<Route path="/patmain" element={<Exp/>} />
<Route path="/adco" element={<PostRequest/>} />
<Route path="/adco1" element={<Exp1/>} />
<Route path="/adco2" element={<Exp2/>} />
<Route path="/adco3" element={<Exp3/>} />
<Route path="/adco4" element={<Exp4/>} />
<Route path="/docc1" element={<Docc/>} />
<Route path="/appoint" element={<Done/>} />
</Routes>
</div>
);
}
export default App;
My index.js file
import React from 'react';
import ReactDom from 'react-dom';
import './index.css';
import App from './App';
import {BrowserRouter} from 'react-router-dom';
import {Appointment} from "./appointment/Context"
ReactDom.render(<BrowserRouter><Appointment><App /></Appointment></BrowserRouter>, document.querySelector('#root'));
My Context Provider file where the state emailinfo is not being updated in this file
import {createContext,useState } from 'react';
import * as React from 'react';
export const Contextforabhishek= createContext({});
export const Appointment=({children})=>{
const [emailinfo, setemailinfo] = useState("NA");//Not Getting Updated at Global Level
const yy={emailinfo,setemailinfo}
return(
<>
<Contextforabhishek.Provider value={yy} >{children}</Contextforabhishek.Provider>
</>
);
}
This is the file from where i want the data, file Patmain to File Appointment. I am using useContext inside this.
import "./Appyss.css";
import { Button, Modal, Dropdown} from "react-bootstrap";
import { useState, useEffect,useContext} from "react";
import { Contextforabhishek } from '../../appointment/Context';
import * as React from 'react';
//import { Link } from 'react-router-dom'
function Patmainss(props) {
return (
<div className="forall">
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
{props.title} {props.Introduction}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>{props.Description}</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
function Patmain() {
const {emailinfo,setemailinfo }=useContext(Contextforabhishek);
const infor=(e)=>{
const m=e.target.id;
setemailinfo(m);
}
console.log(emailinfo);{/* THE STATE IS BEING CHANGED HERE BUT THAT SAME STATE IS NOT OBTAINABE AT FILE APPOINTMENT*/}
const [runing, setRuning] = useState(
{
runing:"2"
},
);
const Runing = (e) => {
setRuning({
runing:"2"
});
};
const [modalShow, setModalShow] = useState(false);
const [Fetchdoc, setFetchdoc] = useState([
{
},
]);
const [doct, setDoct] = useState({
First_Name: "",
Intro:"",
Description: "",
Check_Up_Address:""
});
const [renn,setRenn] = useState({
renn:"a",
});
const handleRenn = (e) => {
Runing();
setRenn({
renn:"a",
});
};
const handleRenn1 = (e) => {
Runing();
setRenn({
renn:"aa",
});
};
const handleRenn2 = (e) => {
Runing();
setRenn({
renn:"aaa"
});
};
const handleRenn3 = (e) => {
Runing();
setRenn({
renn:"aaaa"
});
};
const handleRenn4 = (e) => {
Runing();
setRenn({
renn:"aaaaa"
});
};
useEffect(() => {
if(runing.runing==="2")
{
if(renn.renn==="a"){
fetch("http://localhost:8001/docconfirmed")
.then((res) => res.json())
.then((jsonRes) => setFetchdoc(jsonRes),[]);}
else if(renn.renn==="aa"){
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ practice:'Orthopaedic' })
};
fetch('http://localhost:8001/docconfirmed1',requestOptions )
.then(response => response.json())
.then((jsonRes) => setFetchdoc(jsonRes));
}
else if(renn.renn==="aaa"){
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ practice:'Paediatrician' })
};
fetch('http://localhost:8001/docconfirmed1',requestOptions )
.then(response => response.json())
.then((jsonRes) => setFetchdoc(jsonRes));
}
else if(renn.renn==="aaaa"){
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ practice:'General-Physician' })
};
fetch('http://localhost:8001/docconfirmed1',requestOptions )
.then(response => response.json())
.then((jsonRes) => setFetchdoc(jsonRes));
}
else if(renn.renn==="aaaaa"){
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ practice:'Audiologist' })
};
fetch('http://localhost:8001/docconfirmed1',requestOptions )
.then(response => response.json())
.then((jsonRes) => setFetchdoc(jsonRes));
}
runing.runing="stop";
}
});
const handleClick = (e) => {
setModalShow(true);
const { name, alt,id} = e.target;
setDoct({
First_Name: name,
Intro: id,
Description: alt,
});
};
return (
<div>
<div className="column">
<h2 style={{color:'purple',fontWeight: 'bold'}} className="msgs">Click On The Images To Get More Details On Your-Aid Doctors</h2>
<div style={{marginLeft : 50, marginTop : 20, marginDown : 90, display: "block", width: "30%", height: "40%" }}>
<Dropdown>
<Dropdown.Toggle variant="primary" id="dropdown-basic" style={{paddingTop : 12,paddingLeft : 795, paddingBottom : 12, paddingRight : 20, paddingDown : 100, }}>
<h4 style={{textAlign: 'left',color:'black'}}>
Click Here To Choose The Required Specialisation
</h4>
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item onClick={handleRenn}>View All Doctors</Dropdown.Item>
<Dropdown.Item onClick={handleRenn1}>Orthopaedic</Dropdown.Item>
<Dropdown.Item onClick={handleRenn2}>Paediatrician</Dropdown.Item>
<Dropdown.Item onClick={handleRenn3}>General-Physician</Dropdown.Item>
<Dropdown.Item onClick={handleRenn4}>Audiologist</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</div>
<div
className="forall"
>
{Fetchdoc
.sort((a, b) => {
var titleA = a.title;
var titleB = b.title;
if (titleA < titleB) {
return -1;
}
if (titleA > titleB) {
return 1;
}
return 0;
})
.map((doct) =>{
const First=doct.First_Name;
const Last=doct.Last_Name;
const Lasts=doct.practice;
//const Emaill=doct.Email;
return (
// handleEmailInfo(e.target.id)}
<l1><ul><button onClick={infor} className="btn btn-dark" style={{marginLeft : 200, marginTop : 80, display: "block", width: "15%", height: "40%" }} id={doct.Email} >Book An Appointment With { First }</button>
<div className="mores">
<img
//key={/**/}
id={" ( Call#" +String(doct.Doctors_Phone)+" )"}
src={doct.Image}
alt={String(doct.Description)+" Email-ID# "+String(doct.Email)}
name={String(doct.First_Name)+" "+String(doct.Last_Name)}
width="260"
height="190"
onClick={handleClick}
></img>
<l1 style = {{ marginLeft : 20, color:'black', 'font-size': '32px',fontWeight:100}} > {String(First)+" "+String(Last)}<ul style={{ marginTop : 10, color:'white', 'font-size': '26px',fontWeight:80}}>{String(Lasts)}</ul></l1>
<br></br>
<br></br>
</div>
</ul></l1>
);
})}
</div>
<Patmainss
show={modalShow}
onHide={() => setModalShow(false)}
title={doct.First_Name}
Introduction={doct.Intro}
Description={doct.Description}
/>
</div>
</div>
);
}
export default Patmain;
file Appointment where i want the Context Data to be but the state is always at NA emailinfo doesn't change the state at global level
import * as React from 'react';
import {useContext } from 'react';
import { Contextforabhishek } from './Context';
export default function All(){
const {emailinfo}=useContext(Contextforabhishek);//state is unchanged trying to change the state in Patmain file there it changes but here it doesn't change
console.log("obtained",emailinfo)
return(
<div>
<h1>(Done Page) Book an Appointment with: {emailinfo}</h1>
{/* <button onClick={(e)=>{setemailinfo("ll")}}>click</button> */}
</div>
);
}
It's been days and still cannot figure out why this is happening please help me out
In All component it seems that you havent extract setEmailInfo from your context

How do I refactor the modal into a separate file?

Sorry, React developer newbie. I have a working React Class Component with a popup Modal. It displays when you click on a Item Card:
import React from 'react';
import {
Card, Button, CardImg, CardTitle, CardText, CardGroup,
CardSubtitle, CardBody, CardFooter, CardHeader, CardColumns, CardDeck
} from 'reactstrap';
import Config from 'config';
import { decompressToBase64, formatter } from './common.js'
import "./Item.css";
import Modal from 'react-modal';
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)',
},
};
Modal.setAppElement('#root');
class FeaturedCards extends React.Component {
constructor() {
super();
this.state = {
name: 'React',
apiData: [],
isOpen: false
};
}
async componentDidMount() {
const tokenString = sessionStorage.getItem("token");
const token = JSON.parse(tokenString);
let headers = new Headers({
"Accept": "application/json",
"Content-Type": "application/json",
'Authorization': 'Bearer ' + token.token
});
const response = await fetch(Config.apiUrl + `/api/Items/GetFeaturedItems`, {
method: "GET",
headers: headers
});
const json = await response.json();
console.log(json);
this.setState({ itemList: json });
}
render() {
const items = this.state.itemList;
let subtitle;
handleClick = handleClick.bind(this);
closeModal = closeModal.bind(this);
function handleClick() {
this.setState({ isOpen: true });
}
function closeModal() {
console.log('Clicked close button')
this.setState({ isOpen: false });
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = '#f00';
}
return (
<div>
<CardGroup className="card-group-scroll">
{items && items.map(item =>
<>
<Card key={item.itemNumber} tag="a" onClick={() => handleClick()} style={{ cursor: "pointer" }}>
<CardHeader tag="h3">Featured</CardHeader>
<CardImg top className="card-picture" src={"data:image/png;base64," + decompressToBase64(item.images[0]?.compressedImageData)} id={item.itemNumber + "Img"} alt={item.itemNumber} />
<CardBody className="card-body">
<CardTitle tag="h5">{item.itemNumber}</CardTitle>
<CardSubtitle tag="h6" className="mb-2 text-muted">{item.categoryName}</CardSubtitle>
<CardText className="card-description">{item.itemDescription}</CardText>
</CardBody>
<CardFooter className="text-muted">{formatter.format(item.price)}</CardFooter>
</Card>
<Modal
isOpen={this.state.isOpen}
onAfterOpen={afterOpenModal}
onRequestClose={() => closeModal()}
style={customStyles}
contentLabel={item.itemNumber}>
<h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
<button onClick={() => closeModal()}>close</button>
<div>I am a modal</div>
<form>
<input />
<button>tab navigation</button>
<button>stays</button>
<button>inside</button>
<button>the modal</button>
</form>
</Modal>
</>
)}
</CardGroup>
</div>
);
}
}
export default FeaturedCards;
I need to use this same modal in several different places. I need the modal to have access to the item I clicked on. How do I refactor the modal into a separate file?
Any help would be appreciated.
UPDATE
My first attempt:
import React from 'react';
import "./Item.css";
import Modal from 'react-modal';
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)',
},
};
Modal.setAppElement('#root');
class ItemModal extends React.Component {
constructor(props) {
super(props);
}
render() {
let subtitle;
closeModal = closeModal.bind(this);
function closeModal() {
console.log('Clicked close button')
this.setState({ isOpen: false });
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = '#f00';
}
return (
<Modal
isOpen={this.state.isOpen}
onAfterOpen={afterOpenModal}
onRequestClose={() => closeModal()}
style={customStyles}
contentLabel={this.props.item.itemNumber}>
<h2 ref={(_subtitle) => (subtitle = _subtitle)}>Hello</h2>
<button onClick={() => closeModal()}>close</button>
<div>I am a modal</div>
<form>
<input />
<button>tab navigation</button>
<button>stays</button>
<button>inside</button>
<button>the modal</button>
</form>
</Modal>
);
}
}
export default ItemModal;
I call it from FeaturedCards like this <ItemModal item = { item } />
I get an error: TypeError: this.state is null. I can't seem to figure out how to read(Share) the state from FeaturedCards...
Here is the very basic(with only open and close functionalities) example of how you can create a common modal (there could be other ways...).
class ItemModal extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Modal
isOpen
onRequestClose={this.props.onRequestClose}
>
Sample content
</Modal>
);
}
}
export default ItemModal;
and this can be used like below.
class FeaturedCards extends React.Component {
constructor(props) {
super(props);
this.state = {
isOpen: false
};
}
onRequestClose = () => {
this.setState({isOpen: false});
}
handleClick = () => {
this.setState({ isOpen: true });
}
render() {
const { isOpen } = this.state;
return (
<div>
<button type="button" onClick={this.handleClick}> open Modal</button>
{ isOpen ? <ItemModal onRequestClose={this.onRequestClose} /> : null }
</div>
);
}
}
export default FeaturedCards;

How to use pagination in Reactjs application

I am implementing pagination for my blog page by using react-js-pagination.
I am unable to fix this pagination ui and its content per page
Bind my data accordingly per page
I have tried to import less from bootstrap but it is not rendering for this.
Any suggestion on this to solve this pagination issue?
Updated code: it is working now
//blog.js
import React, {Component} from 'react';
import {Card, Grid, Cell, Dialog, CardMenu, Button, CardTitle,
CardText, CardActions, FABButton, Icon} from'react-mdl';
import { Container} from 'reactstrap';
import { connect } from 'react-redux';
import { getBlog, deleteBlog } from '../../actions/resumeActions';
import PropTypes from 'prop-types';
import Loading from './Loading';
import Moment from 'moment';
import BlogModal from "./BlogModal";
import Pagination from "react-js-pagination";
class Blogs extends Component{
constructor(props) {
super(props);
this.state = {
modal: false,
justClicked: null,
activePage: 1
};
this.handleOpenDialog = this.handleOpenDialog.bind(this);
this.handleCloseDialog = this.handleCloseDialog.bind(this);
}
static propTypes = {
getContact: PropTypes.func.isRequired,
deleteContact: PropTypes.func.isRequired,
resume: PropTypes.object.isRequired,
isAuthenticated: PropTypes.bool,
auth: PropTypes.object.isRequired,
loading: PropTypes.object.isRequired
}
toggle = () => {
this.setState({
modal: !this.state.modal
});
}
handleOpenDialog(id) {
this.setState({
openDialog: true,
justClicked: id
});
}
handleCloseDialog() {
this.setState({
openDialog: false
});
}
componentDidMount() {
this.props.getBlog();
}
onDeleteBlogClick = (id) => {
this.props.deleteBlog(id);
};
handlePageChange(pageNumber) {
console.log(`active page is ${pageNumber}`);
this.setState({activePage: pageNumber});
}
cardDialog(blogs, user){
return(
<Grid style={{padding: 0, display: 'contents'}}>
{blogs.map(({ _id, blog_name, blog_desc, blog_image_link, blog_by }) => (
<Cell col={12}>
<Dialog open={this.state.openDialog && this.state.justClicked === _id} className="open-dialog">
<CardTitle style={{color: '#fff', height: '176px', backgroundImage: `url(${blog_image_link})`, backgroundPosition: 'center',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat'}}>{blog_name}</CardTitle>
<CardText>
{blog_desc}
</CardText>
<CardActions border>
<p style={{float:'right', fontWeight:'bold'}}>Author: {blog_by}</p>
</CardActions>
<CardMenu style={{color: '#fff'}}>
<FABButton onClick={this.handleCloseDialog} className="close-button" >
<Icon name="close" />
</FABButton>
</CardMenu>
</Dialog>
</Cell>
))}
</Grid>
)
}
render(){
const { blogs, loading} = this.props.resume;
const { isAuthenticated, user } = this.props.auth;
const itemsPerPage = 1;
let activeBlogs = blogs.slice (itemsPerPage * this.state.activePage - itemsPerPage, itemsPerPage * this.state.activePage)
return(
<Container>
{loading ? (
<div><Loading/></div>
) : (
<div>
{/* blog modal */}
<BlogModal />
{/* card dialog */}
{this.cardDialog(blogs, user)}
<Grid style={{padding: 0}} id="todo">
{activeBlogs.map(({ _id, blog_name, blog_by, date }) => (
<Cell key={_id} data-id={_id}>
{ this.props.isAuthenticated && (user.is_admin === true) ?
<Button className="remove-btn"
color="danger"
size="sm"
onClick= {this.onDeleteBlogClick.bind(this, _id)}>
×
</Button> : null }
<Card shadow={5} className="cards-grid">
<CardTitle className="card-title-image"></CardTitle>
<CardText>
<b>{blog_name}</b>
</CardText>
<CardActions border>
<Button className="blog-read-me-button" onClick={this.handleOpenDialog.bind(this, _id)}>Read </Button>
<p style={{ fontStyle:'italic', fontWeight:'bold'}}>By-{blog_by} <span style={{float:'right',}}>{Moment(date).format('Do MMMM YYYY')}</span></p>
</CardActions>
</Card>
</Cell>
))}
</Grid>
</div>
)}
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={1}
totalItemsCount={2}
pageRangeDisplayed={1}
onChange={this.handlePageChange.bind(this)}
itemClass='page-item'
linkClass='page-link'
/>
</Container>
)
}
}
const mapStateToProps = (state) => ({
resume: state.resume,
isAuthenticated : state.auth.isAuthenticated,
auth: state.auth,
loading: state.apiCallsInProgress > 0
});
export default connect(mapStateToProps, {getBlog, deleteBlog }) (Blogs);
//current ui
This is the default style of react-js-pagination. You have to style it yourself. However as far as I see, you are using bootstrap in your application, so you could use their styles in the following way:
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={1}
totalItemsCount={2}
pageRangeDisplayed={1}
onChange={this.handlePageChange.bind(this)}
itemClass='page-item'
linkClass='page-link'
/>

How to update image src when opening modal

I have this class component and I'm getting the data from a JSON file by using GraphQL. Everything works as expected but I find hard to update the image src inside of the Modal component when it's open. Data doesn't seems to get passed to the Modal and it shows the same image for all the cards. If I try using props it returns undefined in the image.src.
Any ideas or help on how to solve this would be great!!
my code:
import React from "react"
import { StaticQuery, graphql } from 'gatsby'
import { Container, Row, Col } from 'react-grid-system'
import Modal from 'react-responsive-modal'
class ProjectsList extends React.Component {
constructor(props) {
super(props)
this.state = {
open: false,
}
}
onOpenModal = () => {
this.setState({ open: true, modalImage: this.props });
};
onCloseModal = () => {
this.setState({ open: false });
};
render() {
const projects = this.props;
const { open } = this.state;
return(
<div>
<Row>
{projects.projects.map(item =>(
<Col md={6} key={item.id}>
<div className="project-card">
<div className="project-img-wrap">
<img src={item.image.src.publicURL} alt="projects" onClick={this.onOpenModal} />
</div>
<div className="project-text-wrap">
<span className="project-title">{item.title}</span>
</div>
</div>
<Modal open={open} onClose={this.onCloseModal} center>
<img style={{maxWidth: '800px'}} src={item.image.src.publicURL} alt="projects" />
</Modal>
</Col>
))}
</Row>
</div>
);
}
}
export default props => (
<StaticQuery
query={graphql`
query {
dataJson {
projects {
id
title
image {
src {
publicURL
}
}
}
}
}
`}
render={({ dataJson }) => <ProjectsList projects={dataJson.projects} {...props} />}
/>
)
I've made little edits to your code. That should work out.
The problem is that you haven't passed modalImage from your state to src in Modal image.
import React from "react"
import { StaticQuery, graphql } from 'gatsby'
import { Container, Row, Col } from 'react-grid-system'
import Modal from 'react-responsive-modal'
class ProjectsList extends React.Component {
constructor(props) {
super(props)
this.state = {
open: false,
modalImage: ""
}
}
onOpenModal = (image) => {
this.setState({ open: true, modalImage: image });
};
onCloseModal = () => {
this.setState({ open: false });
};
render() {
const projects = this.props;
const { open, modalImage } = this.state;
return(
<div>
<Row>
{projects.projects.map(item =>(
<Col md={6} key={item.id}>
<div className="project-card">
<div className="project-img-wrap">
<img src={item.image.src.publicURL} alt="projects" onClick={() => this.onOpenModal(item.image.src.publicURL)} />
</div>
<div className="project-text-wrap">
<span className="project-title">{item.title}</span>
</div>
</div>
<Modal open={open} onClose={() => this.onCloseModal()} center>
<img style={{maxWidth: '800px'}} src={modalImage} alt="projects" />
</Modal>
</Col>
))}
</Row>
</div>
);
}
}
export default props => (
<StaticQuery
query={graphql`
query {
dataJson {
projects {
id
title
image {
src {
publicURL
}
}
}
}
}
`}
render={({ dataJson }) => <ProjectsList projects={dataJson.projects} {...props} />}
/>
)

The React.js app sends multiple POST requests instead of a single request

I am developing React.js user interface that sends requests to the Django backend. The problem is that the React.js app sends multiple requests to the backend on a button click event and page reload event.
But I want to send just a single request when a button Predict is clicked in BottomControls.js. What is wrong in my code?
BatchFlights.js
import React, { Component, Fragment } from 'react';
import TopControls from "./layout/batch/TopControls"
import MainContent from "./layout/batch/MainContent"
import BottomControls from "./layout/batch/BottomControls"
import styles from "./layout/styles/styles";
import { withStyles } from "#material-ui/core/styles";
class BatchFlights extends Component {
constructor(props) {
super(props);
this.state = {
csvData: [],
holdingTime: 0,
prediction: 0,
labelWidth: 0
};
this.handleChange = this.handleChange.bind(this);
};
componentDidMount() {
this.fetchData();
};
updateDelay(prediction) {
this.setState(prevState => ({
prediction: prediction
}));
};
setCsvData = csvData => {
this.setState({
csvData
}, () => {
console.log(JSON.stringify(csvData))
});
}
fetchData = () => {
fetch("http://localhost:8000/batch_predict", {
method: "POST",
headers: {
'Accept': 'application/jsonp, text/plain, */*',
//'Content-Type': 'application/json'
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" // otherwise $_POST is empty
},
body: JSON.stringify({
holdingTime: this.state.holdingTime,
csvData: this.state.csvData
})
})
.then((resp) => {
return resp.json()
})
.then((data) => {
this.updateDelay(data.prediction)
})
.catch((error) => {
console.log(error, "catch the hoop")
})
};
handleChange = (name, event) => {
this.setState({
[name]: event.target.value
}, () => {
console.log("plannedDep",this.state.plannedDep)
});
};
handleReset = () => {
this.setState({
prediction: 0
});
};
render() {
return (
<Fragment>
<TopControls state={this.state} styles={this.props.classes} handleChange={this.handleChange} />
<MainContent state={this.state} styles={this.props.classes} setCsvData={this.setCsvData} />
<BottomControls state={this.state} styles={this.props.classes} fetchData={this.fetchData} handleReset={this.handleReset}/>
</Fragment>
);
}
}
const StyledBatchFlights = withStyles(styles)(BatchFlights);
export default StyledBatchFlights;
CSVDataTable.js
import React, { Component } from 'react';
import { CsvToHtmlTable } from 'react-csv-to-table';
import ReactFileReader from 'react-file-reader';
import Button from '#material-ui/core/Button';
const sampleData = `
NUM,AIRLINE_ARR_ICAO,WAKE,SIBT,SOBT,PLANNED_TURNAROUND,DISTANCE_FROM_ORIGIN,DISTANCE_TO_TARGET
1,VLG,M,2016-01-01 04:05:00,2016-01-01 14:10:00,45,2000,2000
2,VLG,M,2016-01-01 04:05:00,2016-01-01 14:10:00,45,2000,2000
`;
class CSVDataTable extends Component {
state={
csvData: sampleData
};
handleFiles = files => {
var reader = new FileReader();
reader.onload = (e) => {
// Use reader.result
this.setState({
csvData: reader.result
})
this.props.setCsvData(reader.result)
}
reader.readAsText(files[0]);
}
render() {
return <div>
<ReactFileReader
multipleFiles={false}
fileTypes={[".csv"]}
handleFiles={this.handleFiles}>
<Button
variant="contained"
color="primary"
>
Load data
</Button>
</ReactFileReader>
<CsvToHtmlTable
data={this.state.csvData || sampleData}
csvDelimiter=","
tableClassName="table table-striped table-hover"
/>
</div>
}
}
export default CSVDataTable;
BottomControls.js
import React, { Component, Fragment } from 'react';
import CssBaseline from '#material-ui/core/CssBaseline';
import Grid from '#material-ui/core/Grid';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardContent from '#material-ui/core/CardContent';
import AppBar from '#material-ui/core/AppBar';
import Button from '#material-ui/core/Button';
import Icon from '#material-ui/core/Icon';
class BottomControls extends Component {
render() {
return (
<Fragment>
<CssBaseline />
<AppBar position="fixed" color="primary" className={this.props.styles.appBar}>
<div className={this.props.styles.toolbar}>
<Grid container spacing={24}>
<Grid item xs={6} sm={3}>
<Button variant="contained" color="primary" onClick={this.props.fetchData} className={this.props.styles.button}>
Predict
<Icon className={this.props.styles.rightIcon}>send</Icon>
</Button>
<Button variant="contained" color="primary" onClick={this.props.handleReset} className={this.props.styles.button}>
Reset
<Icon className={this.props.styles.rightIcon}>clear</Icon>
</Button>
</Grid>
<Grid item xs={6} sm={2}>
<Card className={this.props.styles.predictedDelay}>
<CardActionArea>
<CardContent>
<div className={this.props.styles.predictedDelayText}>
Prediction: {this.props.state.prediction} <span> </span>
</div>
</CardContent>
</CardActionArea>
</Card>
</Grid>
</Grid>
</div>
</AppBar>
</Fragment>
);
}
}
export default BottomControls;
Maybe is because your binding an arrow function, this.handleChange, but I don't see any problem besides that
I deleted this:
componentDidMount() {
this.fetchData();
};
Now the request is sent only on a button click. It is not sent on a page reload.

Categories

Resources