Javascript React JS-子组件的setState回调未更新父组件的状态
我正在尝试构建一个表单应用程序,它将根据父组件状态的“currentView”属性有条件地呈现表单 这是我的父组件Javascript React JS-子组件的setState回调未更新父组件的状态,javascript,reactjs,material-ui,Javascript,Reactjs,Material Ui,我正在尝试构建一个表单应用程序,它将根据父组件状态的“currentView”属性有条件地呈现表单 这是我的父组件 import React from "react"; import Grid from "@material-ui/core/grid"; import Button from "@material-ui/core/button"; import InputHours from "./InputHours&quo
import React from "react";
import Grid from "@material-ui/core/grid";
import Button from "@material-ui/core/button";
import InputHours from "./InputHours";
import ReviewHours from "./ReviewHours";
class Account extends React.Component {
constructor(props) {
super(props);
this.state = { isLoggedOn: true, currentView: "main", formEntries: {} };
}
_setMainView = () => {
this.setState({
currentView: "main",
});
window.alert("the view is now set to main");
};
_setInputView = () => {
this.setState({
currentView: "input",
});
};
_setReviewView = () => {
this.setState({
currentView: "review",
});
};
_returnWithEntries = (entries) => {
window.alert("return is firing");
this.setState({
// formEntries: entries,
currentView: "main",
});
};
render() {
const renderStage = () => {
window.alert("the stage is being rendered");
/**
* HTML for main "stage" view.
*/
if (this.state.currentView === "main") {
return (
<Grid container justify={"center"}>
<Grid item xs={4}>
<InputHours
onClick={this._setInputView}
currentView={this.state.currentView}
/>
</Grid>
<Grid item xs={4}>
<ReviewHours
onClick={this._setReviewView}
currentView={this.state.currentView}
/>
</Grid>
</Grid>
);
/**
* Html for "input" view
*/
} else if (this.state.currentView === "input") {
return (
<Grid item xs={8}>
<InputHours
onClick={this._setInputView}
currentView={this.state.currentView}
finishForm={this._setMainView}
/>
<Button
variant={"contained"}
color={"secondary"}
onClick={this._setMainView}
>
Back
</Button>
</Grid>
);
/**
* HTML for "review" view
*/
} else if (this.state.currentView === "review") {
return (
<Grid item xs={8}>
<ReviewHours
onClick={this._setReviewView}
currentView={this.state.currentView}
/>
<Button
variant={"contained"}
color={"secondary"}
onClick={this._setMainView}
>
Back
</Button>
</Grid>
);
}
};
return (
<div>
<Grid container spacing={4} alignItems={"center"} justify={"center"}>
<Grid item xs={2}></Grid>
{renderStage()}
<Grid item xs={2}></Grid>
</Grid>
</div>
);
}
}
export default Account;
您应该在父窗体中定义一个函数,并通过道具在子窗体中访问该函数并执行它。如果Account是您的父级,那么应该有一个函数finishForm在那里声明并传递到InputHours properties.@Rain.To被调用的函数是在父级组件中定义的_setMainView。finishForm只是保存该函数回调的属性的名称。就像您正在为onClick执行卡上的{()=>this.props.onClick()}一样,您需要在finishForm的相应位置执行相同的操作。请在代码中包含
InputForm
。
class InputHours extends React.Component {
render() {
const classes = styles;
const currentView = this.props.currentView;
const renderForm = () => {
if (currentView === "input") {
return <InputForm finishForm={this.props.finishForm} />;
} else return <p style={classes.root}>Click here to input your hours.</p>;
};
return (
<Card className={classes.root} onClick={() => this.props.onClick()}>
{renderForm()}
</Card>
);
}
import {
FormControl,
FormLabel,
FormControlLabel,
InputLabel,
Input,
FormHelperText,
TextField,
Grid,
Select,
MenuItem,
Radio,
RadioGroup,
FormGroup,
Checkbox,
Button,
withStyles,
} from "@material-ui/core";
import React from "react";
const activities = [
"Attendance at Required Events",
"Drew Honduras Project (DHP)",
"Drew Student Voter Project (DSVP)",
"Changebuilder Program",
"Project Pericles Debating for Democracy Team",
"UPitch Business Development Team",
"Federal Community Work Study",
"Community-Based Learning Project or Placement",
"Community Service Placement (Center for Civic Engagement)",
"Alternative Break Trip",
"Lecture, Panel Discussion, Webinar, Screening, Performance",
"Political Advocacy or Engagement",
"Diversity, Inclusion/Anti-Racism Facilitated Dialouges and Workshops",
"Interfaith Training and Workshops (Center for Religion, Culture, and Conflict)",
"Participation in Student Government",
"Others (add description below)",
];
const mentors = ["Alyssa", "Cassidy", "Janak", "Kate", "Marwa", "Melanie"];
function wordCount(val) {
var wom = val.match(/\S+/g);
return {
charactersNoSpaces: val.replace(/\s+/g, "").length,
characters: val.length,
words: wom ? wom.length : 0,
lines: val.split(/\r*\n/).length,
};
}
const styles = (theme) => ({
formControl: {
minWidth: 190,
},
});
class InputForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: null,
date: null,
hours: null,
activity: null,
type: null,
gainConfidence: false,
valueEmpathy: false,
explore: false,
reflection: "",
mentor: null,
formPage: 1,
};
}
maxWordsExceeded = () => {
var count = wordCount(this.state.reflection).words;
if (count < 150 || count > 250) {
return true;
} else return false;
};
setReflectionWordCountText = () => {
var count = wordCount(this.state.reflection).words;
if (count < 150) {
return "(" + count + " words) Add more detail to your reflection";
} else if (count > 250) {
return "(" + count + " words) Your reflection is too lengthy";
} else return "(" + count + " words)";
};
_handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value,
});
};
_handleChecked = (event) => {
this.setState({
[event.target.name]: event.target.checked,
});
};
_handleSubmit = () => {
this.setState({
formPage: ++this.state.formPage,
});
if (this.state.formPage > 3) {
this.setState({
formPage: 1,
});
// var formEntries = this.state;
// delete formEntries.formPage;
this.props.finishForm();
}
};
render() {
const revealElements = () => {
/* Consider wrapping each form control label in paper */
/* Later versions MUST implement aria controls in all fields*/
if (this.state.formPage === 1) {
return (
<Grid
container
alignItems={"center"}
justify={"space-evenly"}
direction={"row"}
>
<Grid item>
<FormControl>
<InputLabel htmlFor={"name-input"}>Name</InputLabel>
<Input
name={"name"}
id={"name"}
labelId={"name-input"}
aria-describedby={"name-helper"}
onChange={this._handleChange}
/>
<FormHelperText id={"name-helper"}>Name</FormHelperText>
</FormControl>
</Grid>
<Grid item>
<FormControl>
<TextField
name={"date"}
id={"date"}
label={"Date"}
type={"date"}
InputLabelProps={{
shrink: true,
}}
onChange={this._handleChange}
/>
<FormHelperText id={"date-helper"}>
Date of Activity
</FormHelperText>
</FormControl>
</Grid>
<Grid item>
<FormControl>
<InputLabel htmlFor={"hours-input"}>Hours</InputLabel>
<Input
name={"hours"}
id={"hours"}
labelId={"hours-input"}
aria-describedby={"hours-helper"}
onChange={this._handleChange}
/>
<FormHelperText id={"hours-helper"}>
Number of Hours
</FormHelperText>
</FormControl>
</Grid>
</Grid>
);
} else if (this.state.formPage === 2) {
return (
<Grid
container
alignItems={"center"}
justify={"space-evenly"}
direction={"row"}
>
<Grid item>
<FormControl className={this.props.classes.formControl}>
<InputLabel id={"activity-input"}>
Description of Activity
</InputLabel>
<Select
name={"activity"}
labelId={"activity-input"}
id={"activity"}
onChange={this._handleChange}
input={<Input />}
>
{activities.map((element) => (
<MenuItem key={element} value={element}>
{element}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item>
<FormControl component={"fieldset"}>
<FormLabel component={"legend"}>
Type of Experiential Learning Hours
</FormLabel>
<RadioGroup
name={"type"}
onChange={this._handleChange}
aria-label={"type-of-learning-hours"}
>
<FormControlLabel
value={"required"}
control={<Radio />}
label={"Required"}
/>
<FormControlLabel
value={"active not preapprove"}
control={<Radio />}
label={"Active (not requiring preapproval)"}
/>
<FormControlLabel
value={"active preapprove"}
control={<Radio />}
label={"Active (preapproved)"}
/>
<FormControlLabel
value={"receptive"}
control={<Radio />}
label={"Receptive"}
/>
</RadioGroup>
</FormControl>
</Grid>
<Grid item>
<FormControl component={"fieldset"}>
<FormLabel component={"legend"}>
Which program learning goals does this activity help fulfill?
Check all that apply.
</FormLabel>
<FormGroup>
<FormControlLabel
control={
<Checkbox
name={"gainConfidence"}
onChange={this._handleChecked}
/>
}
label="Gain confidence and skills to identify, define and tackle complex problems that
impact communities and transcend borders."
/>
<FormControlLabel
control={
<Checkbox
name={"valueEmpathy"}
onChange={this._handleChecked}
/>
}
label={
"Value empathy, understanding and responsiveness to diverse others in their work and public roles."
}
/>
<FormControlLabel
control={
<Checkbox
name={"explore"}
onChange={this._handleChecked}
/>
}
label={
"Explore and take action on solutions to real-world problems that fulfill the goals of social impact, financial viability, and environmental sustainability."
}
/>
</FormGroup>
</FormControl>
</Grid>
</Grid>
);
} else {
return (
<Grid
container
alignItems={"center"}
justify={"space-evenly"}
direction={"row"}
>
<Grid item>
<FormControl>
<TextField
name={"reflection"}
id={"reflection-input"}
label={"Add Your Reflection"}
multiline={true}
rowsMax={15}
fullWidth={true}
error={this.maxWordsExceeded()}
onChange={this._handleChange}
variant={"outlined"}
color={"primary"}
placeholder={
"Describe how the experiential learning hours were spent. Reflect on how this activity is aligned with the program's learning goals. (150-250 words)"
}
/>
<FormHelperText id={"reflection-helper"}>
{this.setReflectionWordCountText()}
</FormHelperText>
</FormControl>
</Grid>
<Grid item>
<FormControl className={this.props.classes.formControl}>
<InputLabel id="mentor-input">Who Is Your Mentor?</InputLabel>
<Select
name={"mentor"}
labelId={"mentor-input"}
id={"mentor"}
labelWidth={7}
onChange={this._handleChange}
input={<Input fullWidth={true} />}
>
{mentors.map((element) => (
<MenuItem key={element} value={element}>
{element}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
);
}
};
return (
<Grid
container
alignItems={"center"}
justify={"space-evenly"}
direction={"column"}
>
<Grid item>{revealElements()}</Grid>
<Grid item>
<Button onClick={this._handleSubmit}>Submit</Button>
</Grid>
</Grid>
);
}
}
export default withStyles(styles)(InputForm);