我有一个组件MyComp
,其中包含一个长代码,我想将其分为3个组件。
我的目标是获得MyComp
的以下设置。我感谢一般准则和答案中的一个小例子:
import React, { Component, Fragment } from 'react'
import { TopControls, Main, BottomBar } from './layouts'
export default class extends Component {
render() {
return <Fragment>
<TopControls />
<Main />
<BottomBar />
</Fragment>
}
}
下面,我提供代码MyComp
。我的特别疑问是我应该将const styles
和所有功能(例如updateDelay
等,因为它们将在组件TopControls
,Main
和BottomBar
之间共享:
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from '@material-ui/core/styles/withStyles';
import CssBaseline from '@material-ui/core/CssBaseline';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import Icon from '@material-ui/core/Icon';
import TextField from '@material-ui/core/TextField';
import LinePlot from '../chart/LinePlot';
import BrushBarPlot from '../chart/BrushBarPlot';
import FormControl from '@material-ui/core/FormControl';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
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 InputAdornment from '@material-ui/core/InputAdornment';
const styles = theme => ({
header: {
borderBottom: 'solid 1px rgba(0,0,0,0.4)',
backgroundColor: '#253069',
color: '#d2d6ef',
overflow: 'hidden',
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
position: 'relative',
height: '12%'
},
h1: {
fontSize: '30px',
textAlign: 'center',
fontFamily: 'sans-serif',
lineHeight: '1.45em',
webkitFontSmoothing: 'antialiased'
},
h3: {
fontSize: '20px',
textAlign: 'left',
fontFamily: 'sans-serif',
lineHeight: '1.45em',
marginLeft: theme.spacing.unit*2,
webkitFontSmoothing: 'antialiased'
},
appBar: {
top: 'auto',
bottom: 5,
height: '10%'
},
toolbar: {
alignItems: "center",
justifyContent: "space-between"
},
textField: {
fontSize: '12px',
margin: theme.spacing.unit,
minWidth: 120
},
formControl: {
fontSize: '12px',
margin: theme.spacing.unit,
minWidth: 120
},
predictedDelay: {
marginTop: '10px',
position: 'relative',
minWidth: 350,
maxWidth: 350,
textAlign: 'center',
fontFamily: 'sans-serif',
backgroundColor: 'rgb(225, 0, 80)'
},
predictedDelayText: {
fontSize: '18px'
},
topControls: {
borderBottom: '1px solid #ddd',
height: '25%',
boxShadow: '0 1px 4px rgba(0,0,0,0.08)',
background: 'white',
marginLeft: theme.spacing.unit*2,
marginRight: theme.spacing.unit*2,
},
mainPart: {
webkitJustifyContent: 'space-between',
justifyContent: 'space-between',
marginTop: '30px',
marginBottom: '50px',
paddingTop: '2px',
position: 'relative',
backgroundColor: '#f7f7f7'
},
card: {
maxWidth: 200
},
paper: {
backgroundColor: '#f7f7f7',
padding: theme.spacing.unit * 2,
height: '70%',
marginLeft: theme.spacing.unit * 2,
marginRight: theme.spacing.unit * 2,
},
buttons: {
display: 'flex',
justifyContent: 'flex-end',
},
rightIcon: {
marginLeft: theme.spacing.unit,
},
button: {
marginTop: theme.spacing.unit * 3,
marginLeft: theme.spacing.unit,
}
});
class MyComp extends React.Component {
constructor(props) {
super(props);
this.state = {
holdingTime: 1,
plannedDep: "2017-05-24T10:30",
schedTurnd: 45,
asma40: 100,
asma60: 500,
taxiInTime: 9.50,
wake: 84.73,
temperature: 20,
visibility: 5999.66,
windIntensity: 8.0,
arrivalDelay: 5,
distanceTarget: 500,,
delay: 0,
delay_probability: 0,
delay_cat: "NA",
chartDataWake: [],
chartDataTurnaround: [],
chartDataArrivalDelay: [],
chartDataDistanceTarget: [],
labelWidth: 0
};
this.handleChange = this.handleChange.bind(this);
};
componentDidMount() {
this.fetchData();
};
updateDelay(predicted_delay,delay_probability) {
this.state.chartDataWake = [...this.state.chartDataWake, {wake: this.state.wake===84.73 ? "H" : (this.state.wake===14.78 ? "M" : "L"), delay: predicted_delay}];
this.state.chartDataTurnaround = [...this.state.chartDataTurnaround, {turnaround: this.state.schedTurnd, delay: predicted_delay}];
this.state.chartDataArrivalDelay = [...this.state.chartDataArrivalDelay, {arrivalDelay: this.state.arrivalDelay, delay: predicted_delay}];
this.state.chartDataDistanceTarget = [...this.state.chartDataDistanceTarget, {distanceTarget: this.state.distanceTarget, delay: predicted_delay}];
this.setState({
delay: predicted_delay,
delay_probability: delay_probability,
delay_cat: predicted_delay===0 ? "<15" : (predicted_delay===1 ? "[15; 45]" : ">45")
});
};
fetchData = () => {
const url = "http://localhost:8000?"+
'holdingTime='+this.state.holdingTime+
'&plannedDep='+this.state.plannedDep+
'&schedTurnd='+this.state.schedTurnd+
'&asma40='+this.state.asma40+
'&asma60='+this.state.asma60+
'&taxiInTime='+this.state.taxiInTime+
'&wake='+this.state.wake+
'&temperature='+this.state.temperature+
'&visibility='+this.state.visibility+
'&windIntensity='+this.state.windIntensity+
'&arrivalDelay='+this.state.arrivalDelay+
'&distanceTarget='+this.state.distanceTarget;
fetch(url, {
method: "GET",
dataType: "JSON",
headers: {
"Content-Type": "application/json; charset=utf-8",
}
})
.then((resp) => {
return resp.json()
})
.then((data) => {
this.updateDelay(data.prediction,data.probability)
})
.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({
chartDataWake: [],
chartDataTurnaround: [],
chartDataArrivalDelay: [],
chartDataDistanceTarget: [],
delay: 0,
delay_probability: 0,
delay_cat: "NA"
});
};
render() {
const { classes } = this.props;
return (
<React.Fragment>
<CssBaseline />
<div className={classes.header}><h1 className={classes.h1}>Prediction of departure delays for a single flight</h1></div>
<div className={classes.topControls}>
<Grid container spacing={24}>
<Grid item xs={2}>
<TextField
required
id="outlined-simple-start-adornment"
className={classes.textField}
onChange={(event) => this.handleChange("holdingTime", event)}
value={this.state.holdingTime}
margin="normal"
label="Holding time"
type="number"
InputProps={{
startAdornment: <InputAdornment position="start">(seconds)</InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Additional ASMA 40"
onChange={(event) => this.handleChange("asma40", event)}
value={this.state.asma40}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(minutes)</InputAdornment>,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Additional ASMA 60"
onChange={(event) => this.handleChange("asma60", event)}
value={this.state.asma60}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(minutes)</InputAdornment>,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
name="plannedDep"
id="datetime-local"
onChange={(event) => this.handleChange("plannedDep", event)}
value={this.state.plannedDep}
label="Scheduled departure"
type="datetime-local"
className={classes.textField}
margin="normal"
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Planned turnaround"
onChange={(event) => this.handleChange("schedTurnd", event)}
value={this.state.schedTurnd}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(minutes)</InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Taxi-In time"
onChange={(event) => this.handleChange("taxiInTime", event)}
value={this.state.taxiInTime}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(seconds)</InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
</Grid>
<Grid container spacing={24}>
<Grid item xs={2}>
<FormControl
required
className={classes.formControl}
margin="normal">
<InputLabel shrink htmlFor="wake-label-placeholder">
Wake
</InputLabel>
<Select
onChange={(event) => this.handleChange("wake", event)}
value={this.state.wake}
input={<Input name="wake" id="wake-label-placeholder" />}
displayEmpty
name="wake"
>
<MenuItem value={84.73}>Heavy</MenuItem>
<MenuItem value={14.78}>Medium</MenuItem>
<MenuItem value={0.49}>Light</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Temperature"
onChange={(event) => this.handleChange("temperature", event)}
value={this.state.temperature}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(Celsius)</InputAdornment>,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Visibility"
onChange={(event) => this.handleChange("visibility", event)}
value={this.state.visibility}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start"></InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Wind Intensity"
onChange={(event) => this.handleChange("windIntensity", event)}
value={this.state.windIntensity}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(knots)</InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Arrival delay"
onChange={(event) => this.handleChange("arrivalDelay", event)}
value={this.state.arrivalDelay}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(minutes)</InputAdornment>,
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Distance to target"
onChange={(event) => this.handleChange("distanceTarget", event)}
value={this.state.distanceTarget}
type="number"
className={classes.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(km)</InputAdornment>
}}
onInput = {(e) =>{
e.target.value = Math.max(0, parseInt(e.target.value) ).toString().slice(0,12)
}}
/>
</Grid>
</Grid>
</div>
<main className={classes.mainPart}>
<Grid container spacing={24}>
<Grid item xs={12} sm={6} >
<div className={classes.h3}>Wake group</div>
<BrushBarPlot chartData={this.state.chartDataWake} varname="wake"/>
</Grid>
<Grid item xs={12} sm={6} className={classes.card}>
<div className={classes.h3}>Turnaround time</div>
<LinePlot chartData={this.state.chartDataTurnaround} varname="turnaround"/>
</Grid>
<Grid item xs={12} sm={6} >
<div className={classes.h3}>Arrival delay of a flight</div>
<LinePlot chartData={this.state.chartDataArrivalDelay} varname="arrivalDelay"/>
</Grid>
<Grid item xs={12} sm={6} className={classes.card}>
<div className={classes.h3}>Distance to target</div>
<LinePlot chartData={this.state.chartDataDistanceTarget} varname="distanceTarget"/>
</Grid>
</Grid>
</main>
<AppBar position="fixed" color="primary" className={classes.appBar}>
<div className={classes.toolbar}>
<Grid container spacing={24}>
<Grid item xs={6} sm={3}>
<Button variant="contained" color="primary" onClick={this.fetchData} className={classes.button}>
Predict
<Icon className={classes.rightIcon}>send</Icon>
</Button>
<Button variant="contained" color="primary" onClick={this.handleReset} className={classes.button}>
Reset
<Icon className={classes.rightIcon}>clear</Icon>
</Button>
</Grid>
<Grid item xs={6} sm={2}>
<Card className={classes.predictedDelay}>
<CardActionArea>
<CardContent>
<div className={classes.predictedDelayText}>
Delay class: {this.state.delay_cat} <span> </span>
(Prob.: {this.state.delay_probability})
</div>
</CardContent>
</CardActionArea>
</Card>
</Grid>
</Grid>
</div>
</AppBar>
</React.Fragment>
);
}
}
MyComp.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(MyComp);
答案 0 :(得分:0)
只需将通用功能作为prop传递,那么所有孩子都将达到:
render() {
return (
<Fragment>
<TopControls onUpdateDelay={this.updateDelay} />
<Main onUpdateDelay={this.updateDelay} />
<BottomBar onUpdateDelay={this.updateDelay} />
</Fragment>
)
}
此外,您可以将所有常见样式放入外部styles.css
文件中,并将其导入所有组件中,如下所示:
import '../relative/path/to/styles.css';
class MyComp extends React.Component {...
您应该正确设置Webpack,包裹等打包程序,以启用CSS导入。