Dynamically create menu items - javascript

I created an react single page application with the api from NASA Picture of the day. I want to add in a drawer the history of the images displayed but I want to show only it's dates.
I don't know how to create dynamically a list of MenuItem containing this dates. I know only to display the current date.
import React, { Component } from 'react';
import axios from 'axios';
import moment from 'moment';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import RaisedButton from 'material-ui/RaisedButton';
import DatePicker from 'material-ui/DatePicker';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
import AppBar from 'material-ui/AppBar';
import {
cyan500, cyan700,
pinkA200,
grey100, grey300, grey400, grey500,
white, darkBlack, fullBlack,
} from 'C:\\Users\\pitig\\Documents\\SPA\\nasaimages\\node_modules\\material-ui\\styles\\colors';
import logo from './NASA_logo.png';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
controlledDate: moment(),
image: {}
};
}
handleToggle = () => this.setState({ open: !this.state.open });
handleClose = () => this.setState({ open: false });
componentWillMount() {
this.getImage(this.state.controlledDate);
}
getImage = (date) => {
axios({
url: 'https://api.nasa.gov/planetary/apod',
method: 'get',
params: {
api_key: 'qreJekgvmqSs2lqss9dlk2RGveoViwHvXV4T6wlG',
date: date.format('YYYY-MM-DD'),
},
}).then(response => response.data)
.then((image) => {
this.setState({
image: image
})
});
}
handleChange = (event, date) => {
this.setState({
controlledDate: moment(date),
});
this.getImage(moment(date));
};
onNext = (event) => {
const current = this.state.controlledDate;
const date = current.add(1, 'days');
this.setState({
controlledDate: date
});
this.getImage(moment(date));
}
onPrevious = (event) => {
const current = this.state.controlledDate;
const date = current.subtract(1, 'days');
this.setState({
controlledDate: date
});
this.getImage(moment(date));
}
render() {
var muiTheme = getMuiTheme({
palette: {
primary1Color: '#135DAE',
primary2Color: cyan700,
primary3Color: grey400,
accent1Color: '#EF243A',
accent2Color: grey100,
accent3Color: grey500,
},
appBar: {
height: 50,
},
})
return (
<MuiThemeProvider muiTheme={muiTheme}>
<div className="App">
<AppBar
title="NASA: Image of the day"
iconClassNameRight="muidocs-icon-navigation-expand-more"
onLeftIconButtonTouchTap={this.handleToggle}
/>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to NASA: Image of the day</h1>
</header>
<p className="App-intro">
Pick the date you want.
</p>
<DatePicker
hintText="Selected day"
value={this.state.controlledDate.toDate()}
onChange={this.handleChange}
autoOk
/>
<RaisedButton
label="Previous"
secondary={true}
onClick={this.onPrevious}
/>
<RaisedButton
label="Next"
primary={true}
onClick={this.onNext}
/>
<h1>{this.state.image.title}</h1>
<img src={this.state.image.url} />
<div>
<Drawer
docked={false}
width={200}
open={this.state.open}
onRequestChange={(open) => this.setState({ open })}
>
<MenuItem onClick={this.handleClose}>{this.state.image.date}</MenuItem>
</Drawer>
</div>
</div>
</MuiThemeProvider>
);
}
}
export default App;

Make history of dates to Array as state then when you get image, add image date to that array.
And display like this.
<Drawer
docked={false}
width={200}
open={this.state.open}
onRequestChange={(open) => this.setState({ open })}
>
{this.state.history.map((el,index)=>{
return <MenuItem key={index} onClick={this.handleClose}>{el}</MenuItem>;
}
}
</Drawer>

Related

Each child in a list should have a unique "key" prop Error [duplicate]

This question already has answers here:
Understanding unique keys for array children in React.js
(27 answers)
Closed 4 months ago.
Currently I am working on a project using React, Next.js and Ant-Design.
While working on my project, I got an error because I didn't use a unique key like this:
Below is the detailed error log.
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `ForwardRef`. It was passed a child from BoardCard. See https://reactjs.org/link/warning-keys for more information.
at eval (webpack-internal:///./node_modules/antd/es/popover/index.js:30:31)
at eval (webpack-internal:///./node_modules/antd/es/card/Card.js:58:62)
at article
at BoardCard (webpack-internal:///./components/MyPage/BoardCard.js:34:19)
at li
at InternalItem (webpack-internal:///./node_modules/antd/es/list/Item.js:65:31)
at ul
at div
at div
at Spin (webpack-internal:///./node_modules/antd/es/spin/index.js:94:90)
at SpinFC (webpack-internal:///./node_modules/antd/es/spin/index.js:222:34)
at div
at List (webpack-internal:///./node_modules/antd/es/list/index.js:58:26)
at section
at BoardList (webpack-internal:///./components/MyPage/BoardList.js:22:78)
at section
at MyBoard
at section
at MyInfo
at header
at O (webpack-internal:///./node_modules/styled-components/dist/styled-components.browser.esm.js:31:19811)
at AppLayout (webpack-internal:///./components/AppLayout/index.js:28:23)
at profile
at App (webpack-internal:///./pages/_app.js:28:24)
at Provider (webpack-internal:///./node_modules/react-redux/es/components/Provider.js:13:3)
at Wrapper (webpack-internal:///./node_modules/next-redux-wrapper/es6/index.js:184:35)
at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/client.js:8:20746)
at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/client.js:8:23395)
at Container (webpack-internal:///./node_modules/next/dist/client/index.js:241:5)
at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:833:24)
at Root (webpack-internal:///./node_modules/next/dist/client/index.js:986:26)
As a result of checking the error log, it was confirmed that the error occurred in the Boardlist and BoardCard components.
So I checked the key of the relevant component, but I am using a unique key.
import React from 'react';
import { useSelector } from 'react-redux';
import { List } from 'antd';
import BoardCard from './BoardCard';
const BoardList = () => {
const { boardPosts } = useSelector((state) => state.user);
return (
<section>
<List
itemLayout="vertical"
bordered
size="large"
pagination={{
onChange: (page) => console.log(page), pageSize: 3,
}}
dataSource={boardPosts}
renderItem={(item) => (
<List.Item>
<BoardCard post={item} key={item.id}/>
</List.Item>
)}
/>
</section>
)
};
export default BoardList;
import React, { useState, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Card, Modal, Button, Popover, Row, Col, message } from 'antd';
import PropTypes from 'prop-types';
import PostModal from '../Modal/PostModal';
import PostDeleteModal from '../HomePost/PostDeleteModal';
import {
likePostRequestAction, unLikePostRequestAction,
moveToCommentRequestAction, returnToCommentRequestAction
} from '../../reducers/post';
import {
BoardCardHeader, BoardCardBody, MoreIcon, ColWrapper, CardTextWrapper,
CardTitle, CardText, CardContent, HeaderBtn, TwoToneHeartBtnIcon,
HeartBtnIcon, CommentBtnIcon, CardImageWrapper, ImageWrapper
} from './styles';
const BoardCard = ({ post }) => {
const dispatch = useDispatch();
const [visible, setVisible] = useState(false);
const id = useSelector((state) => state.user.me.id);
const liked = post.Likers.find((v) => v.id === id);
const onLikePost = useCallback(() => {
dispatch(likePostRequestAction(post.id));
}, []);
const unLikePost = useCallback(() => {
dispatch(unLikePostRequestAction(post.id));
}, []);
const showPostModal = useCallback(() => {
setVisible(true);
}, []);
const boardCardCommentBtn = useCallback(() => {
setVisible(true);
dispatch(moveToCommentRequestAction());
}, []);
const boardmodalOkBtn = useCallback(() => {
setVisible(false);
dispatch(returnToCommentRequestAction());
}, []);
const boardmodalCancelBtn = useCallback(() => {
setVisible(false);
dispatch(returnToCommentRequestAction());
}, []);
return (
<article>
<Card
headStyle={BoardCardHeader}
bodyStyle={BoardCardBody}
hoverable
extra={[
<Popover
trigger="click"
content={
<>
<Button>Modify</Button>
<PostDeleteModal post={post} />
</>
}
>
<MoreIcon key="ellipsis"/>
</Popover>
]}
>
<Row>
<ColWrapper xs={24} md={16}>
<CardTextWrapper>
<CardText
title={<CardTitle>{post.title}</CardTitle>}
description={post.desc}
onClick={showPostModal}
/>
<CardContent onClick={showPostModal}>{post.recipes}</CardContent>
</CardTextWrapper>
<div>
{
liked
? <HeaderBtn type='text' icon={<TwoToneHeartBtnIcon twoToneColor="#eb2f96" onClick={unLikePost} />}>{post.Likers.length}</HeaderBtn>
: <HeaderBtn type='text' icon={<HeartBtnIcon />} onClick={onLikePost}>{post.Likers.length}</HeaderBtn>
}
<HeaderBtn type='text' icon={<CommentBtnIcon />} onClick={boardCardCommentBtn} >{post.Comments.length}</HeaderBtn>
</div>
</ColWrapper>
<Col xs={24} md={8}>
<CardImageWrapper>
<ImageWrapper
alt="board image"
src={`http://localhost:3065/${post.Images[0]?.src}`}
onClick={showPostModal}
/>
</CardImageWrapper>
</Col>
</Row>
</Card>
<Modal
centered
visible={visible}
onOk={boardmodalOkBtn}
onCancel={boardmodalCancelBtn}
width={1000}
>
<PostModal post={post} />
</Modal>
</article>
);
};
BoardCard.propTypes = {
post: PropTypes.shape({
id: PropTypes.number,
User: PropTypes.object,
title: PropTypes.string,
desc: PropTypes.string,
content: PropTypes.arrayOf(PropTypes.object),
Images: PropTypes.arrayOf(PropTypes.object),
tag: PropTypes.string,
Comments: PropTypes.arrayOf(PropTypes.object),
})
};
export default BoardCard;
I tried to solve the problem, but couldn't find a way.
So, I would like to know why the above problem occurs and how to solve it.
You must put the key on the first child
const BoardList = () => {
const { boardPosts } = useSelector((state) => state.user);
return (
<section>
<List
itemLayout="vertical"
bordered
size="large"
pagination={{
onChange: (page) => console.log(page), pageSize: 3,
}}
dataSource={boardPosts}
renderItem={(item) => (
<List.Item key={item.id}>
<BoardCard post={item}/>
</List.Item>
)}
/>
</section>
)
};

Call function from material ui fonction

I want to pass a function as a props to my material ui function.
The given function is undefined in my material ui fonction.
import React, { Component } from 'react';
import styled from 'styled-components';
import InputBase from '#material-ui/core/InputBase';
import IconButton from '#material-ui/core/IconButton';
import Menu from '#material-ui/core/Menu';
import MenuItem from '#material-ui/core/MenuItem';
import SearchIcon from '#material-ui/icons/Search';
import Avatar from '#material-ui/core/Avatar';
import '../../css/App.css';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { withTranslation } from 'react-i18next';
import CreateNewGarden from './CreateNewGarden';
class Dashboard extends Component {
constructor(props) {
super(props);
this.state = {
};
this.myFunction = this.myFunction.bind(this);
}
myFunction() {
console.log("OK")
}
render() {
return (
<div>
<CreateNewGarden myFunction={this.myFunction}/>
</div>
);
}
}
const mapStateToProps = (state) => ({
});
Dashboard.propTypes = {
};
export default withTranslation()(withRouter(connect(mapStateToProps)(Dashboard)));
I send CreateNewGarden myFunction={this.myFunction} as a props and in my others file.
I have:
import React from 'react';
import { withStyles } from '#material-ui/core/styles';
import Dialog from '#material-ui/core/Dialog';
import MuiDialogTitle from '#material-ui/core/DialogTitle';
import MuiDialogContent from '#material-ui/core/DialogContent';
import MuiDialogActions from '#material-ui/core/DialogActions';
import IconButton from '#material-ui/core/IconButton';
import CloseIcon from '#material-ui/icons/Close';
import Typography from '#material-ui/core/Typography';
import Slider from '#material-ui/core/Slider';
import { useTranslation } from 'react-i18next';
import measureLogo from '../../assets/images/measure.png';
import { Button } from '../../components';
const styles = (theme) => ({
root: {
margin: 0,
padding: theme.spacing(2),
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500],
}
});
const DialogTitle = withStyles(styles)((props) => {
const {
children, classes, onClose, ...other
} = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
<CloseIcon />
</IconButton>
) : null}
</MuiDialogTitle>
);
});
const DialogContent = withStyles((theme) => ({
root: {
padding: theme.spacing(2)
}
}))(MuiDialogContent);
const DialogActions = withStyles((theme) => ({
root: {
margin: 0,
padding: theme.spacing(1)
}
}))(MuiDialogActions);
export default function CustomizedDialogs(props) {
const [open, setOpen] = React.useState(false);
// eslint-disable-next-line no-unused-vars
const [height, setHeight] = React.useState(0);
// eslint-disable-next-line no-unused-vars
const [width, setWidth] = React.useState(0);
console.log("ici = " + props.myFunction)
const setSizeHeight = () => (e, value) => {
setHeight(value);
};
const setSizeWidth = () => (e, value) => {
setWidth(value);
};
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const { t } = useTranslation();
return (
<div className="marginCardComponent">
<Button
onClick={handleClickOpen}
text="dashboard.createGardenBtn"
type="submit"
/>
<Dialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open}>
<DialogTitle id="customized-dialog-title" className="centerText" onClose={handleClose}>
{t('dashboard.createGardenTitle')}
</DialogTitle>
<DialogContent className="logoMeasureParent">
<img src={measureLogo} alt="Logo" className="logoMeasure centerText" />
</DialogContent>
<DialogContent dividers>
<Typography className="centerText" gutterBottom>
{ t('dashboard.createGardenDetail') }
</Typography>
</DialogContent>
<div className="marginLeft3">
<p>{ t('dashboard.height') }</p>
</div>
<div className="centerSlider">
<Slider
/* eslint-disable-next-line react/destructuring-assignment */
defaultValue={0}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
step={1}
marks
min={1}
max={20}
onChange={setSizeHeight()}
/>
</div>
<div className="marginLeft3">
<p>{ t('dashboard.width') }</p>
</div>
<div className="centerSlider">
<Slider
/* eslint-disable-next-line react/destructuring-assignment */
defaultValue={0}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
step={1}
marks
min={1}
max={20}
onChange={setSizeWidth()}
/>
</div>
<DialogActions>
<Button
onClick={handleClose}
text="dashboard.cancelBtn"
type="submit"
/>
<Button
onClick={props.myFunction}
text="dashboard.createGardenBtn"
type="submit"
/>
</DialogActions>
</Dialog>
</div>
);
}
When i click on the button it does nothing and when i print myFunction it tell me undefined.
Why i can't give a props to the function and call myFunction ?
Thank you for your help.
You need to call it outside of onClick. Do it like this:
const handleClick = (e) => {
e.preventDefault()
props.myFunction()
}
And in the button:
<Button
onClick={handleClick}
text="dashboard.createGardenBtn"
type="submit"
/>
That will work. It just isnt letting you call it inside onClick
You can also just do this:
<Button
onClick={() => props.myFunction()}
text="dashboard.createGardenBtn"
type="submit"
/>

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} />}
/>
)

how to edit and delete in api data table in reactjs

I am new to React. Currently, I am doing API fetch and displaying it in a table and adding edit delete in that table. I am successfully fetching API and I can add a new row along with API data, but I don't know how to edit and delete it. I have seen some questions but my code structure is different so I am unable to find the answer. Does any help please?
here is my code,
import React from 'react';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import { makeStyles,withStyles } from '#material-ui/core/styles';
import Fab from '#material-ui/core/Fab';
import AddIcon from '#material-ui/icons/Add';
import EditIcon from '#material-ui/icons/Edit';
import TextField from '#material-ui/core/TextField';
import Dialog from '#material-ui/core/Dialog';
import DialogActions from '#material-ui/core/DialogActions';
import DialogContent from '#material-ui/core/DialogContent';
import DialogContentText from '#material-ui/core/DialogContentText';
import DialogTitle from '#material-ui/core/DialogTitle';
import Button from '#material-ui/core/Button';
const useStyles = theme => ({
fab: {
margin: theme.spacing(1),
},
extendedIcon: {
marginRight: theme.spacing(1),
},
});
const Post = ({ body }) => {
  return (
    <table className=" table-striped">
      <thead>
       <tr>
      <th>Id</th>
      <th>Title</th>
      <th>Content</th>
      
      </tr>
      </thead>
      <tbody>
{body.map(post => {
const { _id, title, content } = post;
return (
 <tr key={_id}>
            <td> {_id!=''?_id: '-'}</td>
            
            <td> {title!='' ?title: '-'}</td>
            
            <td> {content!=''?content: '-'}</td>
<hr />
</tr>
);
})}
</tbody>
</table>
);
};
class App extends React.Component {
state = {
isLoading: true,
posts: [],
error: null,
open:false,
newData:[
{
_id:'',
title:'',
content:''
}
]
};
fetchPosts() {
const axios = require('axios');
axios
.get("https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/posts.json")
.then(response => {
this.setState({
posts: response.data.posts,
isLoading: false,
})
//)
} )
}
componentDidMount() {
this.fetchPosts();
}
handleClickOpen = () =>
this.setState({
open:true
})
;
handleClose = () =>
this.setState({
open:false
})
;
// handleClick = () =>
// {
// {this.handleClickOpen}
// {this.addItem}
// }
// ;
addItem = () =>
{
var temp = [];
var tempPosts = this.state.posts;
var newData = this.state.newData[0];
console.log(this.state.newData)
if(this.state.newData[0]._id && this.state.newData[0].title && this.state.newData[0].content){
tempPosts.push(newData);
console.log(tempPosts)
this.setState({posts: tempPosts})
}
}
render() {
const { isLoading, posts } = this.state;
return (
<React.Fragment>
<h1>React Fetch - Blog</h1>
<div>
<Button variant="outlined" color="primary" onClick=
{this.handleClickOpen}
>
Add
</Button>
<Dialog open={this.state.open} onClose={this.handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">Subscribe</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
id="_id"
label="id"
value={this.state.newData._id}
onChange={(e)=> {
let{ newData } = this.state;
newData[0]._id=e.target.value;
this.setState({newData})
}}
type="text"
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="title"
label="title"
value={this.state.newData.title}
onChange={(e)=> {
let{newData} =this.state;
newData[0].title=e.target.value;
this.setState({newData})
}}
type="text"
fullWidth
/>
<TextField
autoFocus
margin="dense"
id="content"
label="content"
value={this.state.newData.content}
onChange={(e)=> {
let{newData} =this.state;
newData[0].content=e.target.value;
this.setState({newData})
}}
type="text"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
this.addItem()
this.handleClose()
}}
color="primary">
Add
</Button>
<Button onClick={this.handleClose} color="primary">
cancel
</Button>
</DialogActions>
</Dialog>
</div>
<hr />
{!isLoading ? <Post body={posts} /> : <h3>Loading...</h3>}
</React.Fragment>
);
}
}
export default withStyles(useStyles)(App);

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