我正在尝试更好地构建我的初始代码。
https://codesandbox.io/s/jqvkqy29w
但是,我在集成子组件方面遇到问题。作为示例,我展示了如何导入子组件TopControls
。另外,我不确定我是否正确导入了styles
。
下面,我显示一个主要根组件的代码。问题是页面为空,并且未加载TopControls
。打开控制台时,看到以下警告和错误(我使用"react": "^16.6.0"
和"react-dom": "^16.6.0"
)。
警告:React.createElement:类型无效-预期为字符串 (对于内置组件)或类/函数(对于复合 组件),但得到:对象。您可能忘记了导出 定义文件中的组件,否则您可能混淆了 默认导入和命名导入。
在Main.js:113中检查代码。 在_default中(在App.js:21) 在App中(位于src / index.js:5)
react-dom.development.js:57未捕获的错误:元素类型无效: 预期的字符串(用于内置组件)或类/函数(用于 复合组件),但得到了:对象。您可能忘记了出口 您的组件来自定义它的文件,或者您可能已经混合了 设置默认名称并命名导入。
检查
_default
的渲染方法。 不变(react-dom.development.js:57) 在createFiberFromTypeAndProps(react-dom.development.js:10531) 在createFiberFromElement(react-dom.development.js:10551) 在createChild(react-dom.development.js:13811) 在reconcileChildrenArray(react-dom.development.js:14080) 在reconcileChildFibers(react-dom.development.js:14430) 在reconcileChildren(react-dom.development.js:14817) 在finishClassComponent(react-dom.development.js:15161) 在updateClassComponent(react-dom.development.js:15096) 在beginWork(react-dom.development.js:15980) 在performUnitOfWork(react-dom.development.js:19102) 在workLoop(react-dom.development.js:19143) 在HTMLUnknownElement.callCallback(react-dom.development.js:147) 在Object.invokeGuardedCallbackDev(react-dom.development.js:196) 在invokeGuardedCallback(react-dom.development.js:250) 在replayUnitOfWork(react-dom.development.js:18350) 在renderRoot(react-dom.development.js:19261) 在performWorkOnRoot(react-dom.development.js:20165) 在performWork(react-dom.development.js:20075) 在performSyncWork(react-dom.development.js:20049) 在interactiveUpdates $ 1(react-dom.development.js:20337) 在InteractiveUpdates(react-dom.development.js:2267) 在dispatchInteractiveEvent(react-dom.development.js:5083)不变@ react-dom.development.js:57 createFiberFromTypeAndProps @ react-dom.development.js:10531 createFiberFromElement @ react-dom.development.js:10551 createChild @ react-dom.development.js:13811 reconcileChildrenArray @ react-dom.development.js:14080 reconcileChildFibers @ react-dom.development.js:14430 reconcileChildren @ react-dom.development.js:14817 finishClassComponent @ react-dom.development.js:15161 updateClassComponent @ react-dom.development.js:15096 beginWork @ react-dom.development.js:15980 performUnitOfWork @ react-dom.development.js:19102 workLoop @ react-dom.development.js:19143 callCallback @ react-dom.development.js:147 invokeGuardedCallbackDev @ react-dom.development.js:196 invokeGuardedCallback @ react-dom.development.js:250 replayUnitOfWork @ react-dom.development.js:18350 renderRoot @ react-dom.development.js:19261 performWorkOnRoot @ react-dom.development.js:20165 performWork @ react-dom.development.js:20075 performSyncWork @ react-dom.development.js:20049互动更新$ 1 @ react-dom.development.js:20337互动更新@ react-dom.development.js:2267 dispatchInteractiveEvent @ react-dom.development.js:5083 index.js:1446发生上述错误 在<_default>组件中: 在_default中(在App.js:21) 在App中(位于src / index.js:5)
根组件“ Main.js”:
import React, { Component, Fragment } from 'react';
import TopControls from "./layout/single/TopControls"
import styles from "./layout/single/styles"
export default class extends 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,
airport: "LEBL",
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() {
return <Fragment>
<TopControls state={this.state} handleChange={this.handleChange} styles={styles} />
</Fragment>
}
}
styles.js
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,
}
});
TopControls
import React, { Component, Fragment } from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import Grid from '@material-ui/core/Grid';
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 TextField from '@material-ui/core/TextField';
import InputAdornment from '@material-ui/core/InputAdornment';
export default class extends Component {
render() {
return (
<Fragment>
<CssBaseline />
<div className={this.props.styles.header}>
<h1 className={this.props.styles.h1}>
Prediction of departure delays for a single flight
</h1>
</div>
<div className={this.props.styles.topControls}>
<Grid container spacing={24}>
<Grid item xs={2}>
<TextField
required
id="outlined-simple-start-adornment"
className={this.props.styles.textField}
onChange={(event) => this.props.handleChange("holdingTime", event)}
value={this.props.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.props.handleChange("asma40", event)}
value={this.props.state.asma40}
type="number"
className={this.props.styles.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(seconds)</InputAdornment>,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Additional ASMA 60"
onChange={(event) => this.props.handleChange("asma60", event)}
value={this.props.state.asma60}
type="number"
className={this.props.styles.textField}
margin="normal"
InputProps={{
startAdornment: <InputAdornment position="start">(seconds)</InputAdornment>,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
name="plannedDep"
id="datetime-local"
onChange={(event) => this.props.handleChange("plannedDep", event)}
value={this.props.state.plannedDep}
label="Scheduled departure"
type="datetime-local"
className={this.props.styles.textField}
margin="normal"
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={2}>
<TextField
required
id="standard-number"
label="Planned turnaround"
onChange={(event) => this.props.handleChange("schedTurnd", event)}
value={this.props.state.schedTurnd}
type="number"
className={this.props.styles.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.props.handleChange("taxiInTime", event)}
value={this.props.state.taxiInTime}
type="number"
className={this.props.styles.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={this.props.styles.formControl}
margin="normal">
<InputLabel shrink htmlFor="wake-label-placeholder">
Wake
</InputLabel>
<Select
onChange={(event) => this.props.handleChange("wake", event)}
value={this.props.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.props.handleChange("temperature", event)}
value={this.props.state.temperature}
type="number"
className={this.props.styles.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.props.handleChange("visibility", event)}
value={this.props.state.visibility}
type="number"
className={this.props.styles.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.props.handleChange("windIntensity", event)}
value={this.state.windIntensity}
type="number"
className={this.props.styles.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.props.handleChange("arrivalDelay", event)}
value={this.props.state.arrivalDelay}
type="number"
className={this.props.styles.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.props.handleChange("distanceTarget", event)}
value={this.props.state.distanceTarget}
type="number"
className={this.props.styles.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>
</Fragment>
);
}
}
有人知道问题出在哪里吗?
更新:
我也尝试过这个,但是它给了我同样的错误:
const TopControls = () => (
...
);
export default TopControls;
App.js
import React, { Component } from "react";
import SelectionPage from "../modes/SelectionPage";
import Main from "../modes/Main";
import Main2 from "../modes/Main2";
class App extends Component {
state = {
renderView: 0
};
clickBtn = e => {
console.log(e.target.value);
this.setState({
renderView: +e.target.parentNode.value
});
};
render() {
switch (this.state.renderView) {
case 1:
return <Main />;
case 2:
return <Main2 />;
default:
return <SelectionPage clickBtn={this.clickBtn} />;
}
}
}
export default App;
答案 0 :(得分:1)
似乎您无法将state
直接传递给子组件。您可以通过两种主要方法来解决该问题。
您可以将这些值作为props
传递。将state={this.state}
更改为...this.state
(扩展运算符):
render() {
return <Fragment>
<TopControls handleChange={this.handleChange} styles={styles} ...this.state/>
</Fragment>
}
并直接从props
中的TopControls.js
获取这些值:
render() {
...
value={this.props.holdingTime}
...
}
只需使用其他道具传递状态即可:
render() {
return <Fragment>
<TopControls myState={this.state} handleChange={this.handleChange} styles={styles} />
</Fragment>
}
render() {
...
value={this.props.myState.holdingTime}
...
}
答案 1 :(得分:0)
在return
的{{1}}函数下使用render
语句。
app.js
我对代码进行了一些修改,但这是相同的想法。