如何在单击下一步按钮时保存 Mobile Stepper 进度
How to save the Mobile Stepper progress on click of next button
我想保存 Mobile Stepper 的进度状态,这样当用户注销时,用户可以从他离开的地方继续。如果进度条填充了 2%,那么下次用户登录时,他应该从 2% 恢复,而不是从 0 恢复。
这是代码:
import React, { useState, useReducer, useEffect } from "react";
import { Button, Typography, Grid, CircularProgress, Paper } from '@mui/material/';
import guardianOptions from '../../../constants/guardianOptions.js';
import studentClasses from '../../../constants/studentClasses.js';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import StepLabel from '@mui/material/StepLabel';
import MobileStepper from '@mui/material/MobileStepper';
import StepContent from '@mui/material/StepContent';
import { makeStyles, withStyles, createStyles } from '@mui/styles';
import { purple } from '@mui/material/colors';
import TextField from '@mui/material/TextField';
import useStyles from './styles';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormHelperText from '@mui/material/FormHelperText';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
const User= (props) => {
const { activeStep: lastActiveStep, userId } = props;
const classes = useStyles();
const [guardianType, setGuardianType] = useState(0);
const [activeStep, setActiveStep] = useState(lastActiveStep || 0);
const [guardianRelationOptions, setGuardianRelationOptions] = useState(0);
const [guardianDetailsForm, setGuardianDetailsForm] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{}
);
const [studentDetailsForm, setStudentDetailsForm] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{ s_firstName: '', s_lastName: '', s_age: '', s_class: '' }
);
React.useEffect(() => {
async function updateActiveStep() {
// this is just pseudo code - whatever your endpoint looks like
await window.fetch('http://localhost:8080/api/user/:userId', {
method: 'PUT',
body: JSON.stringify({activeStep})
})
}
updateActiveStep()
}, [activeStep]);
function getSteps(){
return [<b style={{color:'purple'}}>'Personal Details'</b>,
<b style={{color:'purple'}}>'Relation'</b>,
<b style={{color:'purple'}}>'Guardian Details'</b>];
}
const steps = getSteps();
function onGuardianTypeChangeChange(event) {
// setAge(event.target.value);
setGuardianType(event.target.value);
let _guardianRelationOptions = guardianOptions.find(options => options.value === event.target.value);
setGuardianRelationOptions(_guardianRelationOptions.relationships);
}
const handleGuardianDeatilsInput = evt => {
const name = evt.target.name;
const newValue = evt.target.value;
setGuardianDetailsForm({ [name]: newValue });
};
const handleGuardianDetailsSubmit = evt => {
evt.preventDefault();
let data = { guardianDetailsForm };
props.onGuardianDetails(guardianDetailsForm)
console.log(data + "new user");
// console.log( props.onGuardianDetails(guardianDetailsForm) + "gana bajao");
setActiveStep((prevActiveStep) => prevActiveStep+1);
setGuardianDetailsForm();
}
function getStepContent(step) {
switch (step) {
case 0: if (!props.user.s_firstName) {
return (<div>
<form id ="form-step0" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<TextField
id="outlined-basic"
name="s_firstName"
label="First Name"
variant="outlined"
defaultValue={guardianDetailsForm.s_firstName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-basic"
name="s_lastName"
label="Last Name"
variant="outlined"
defaultValue={guardianDetailsForm.s_lastName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-number"
label="Age"
name="s_age"
defaultValue={guardianDetailsForm.s_age}
type="number"
InputLabelProps={{
shrink: true,
}}
onChange={handleGuardianDeatilsInput}
variant="outlined"
/>
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Class</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={guardianDetailsForm.s_class}
onChange={handleGuardianDeatilsInput}
label="Class"
name="s_class"
>
{studentClasses.map(c =>
<MenuItem key={c.value} value={c.value}>{c.name}</MenuItem>
)}
</Select>
{/* <Button variant="contained" type="submit" color="primary" >NEXT</Button> */}
</FormControl>
</form>
</div> )}
;
case 1: if (!props.user.g_relationship) {
return ( <div>
<form id="form-step1" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Relationship</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
onChange={onGuardianTypeChangeChange}
label="Relationship"
>
{guardianOptions.map(type =>
<MenuItem key={type.value} value={type.value}>{type.name}</MenuItem>
)}
</Select>
</FormControl>
{guardianRelationOptions ?
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Relation</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
// value={age}
name="g_relationship"
value={guardianDetailsForm.g_relationship}
onChange={handleGuardianDeatilsInput}
label="Relation"
>
{guardianRelationOptions.map(type =>
<MenuItem key={type.value} value={type.value}>{type.name}</MenuItem>
)}
</Select>
</FormControl> : null
}
{!g_relationship} onClick={() => props.onGuardianDetails({g_relationship})}>NEXT</Button> */}
{/* <Button variant="contained" color="primary" type="submit">NEXT</Button> */}
</form>
</div> )}
;
case 2:
return ( <div>
<form id="form-step2" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<TextField
id="outlined-basic"
name="g_firstName"
label="First Name"
variant="outlined"
defaultValue={guardianDetailsForm.g_firstName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-basic"
name="g_lastName"
label="Last Name"
variant="outlined"
defaultValue={guardianDetailsForm.g_lastName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-number"
label="Age"
name="g_age"
defaultValue={guardianDetailsForm.g_age}
type="number"
InputLabelProps={{
shrink: true,
}}
onChange={handleGuardianDeatilsInput}
variant="outlined"
/>
</form>
</div>)
;
default:
return 'welcome lets fill the progress.' ;
}
}
return (
<div className={classes.root} align="center">
<div className = {classes.actionsContainer}>
<Paper square elevation={0}>
<Typography>{getStepContent(activeStep)}</Typography>
</Paper>
<MobileStepper
variant="progress"
steps= {4}
position="bottom"
activeStep={activeStep}
sx={{ minWidth: 400, flexGrow: 1 }}
nextButton={
<>
<Button size="small" onClick={handleGuardianDetailsSubmit} type="submit"
form={`form-step${activeStep}`}>
{activeStep === steps.length-1? 'Finish' : 'Next'}
</Button>
</>
}
/>
</div>
</div>
);
}
export default User;
如果用户刷新或重新加载页面,他应该从他离开的地方看到进度。
@Tanya
所以你是说你的用户可以授权。发生这种情况时,您会收到有关用户的任何数据吗?您可以通过 POST 或 PUT 请求更新用户数据吗?如果是这样,我将使用此数据存储活动步骤。
假设您有一些在用户登录时收到的用户数据:
// user - user data
export default function BuildAdStepper({user}) {
const { activeStep: lastActiveStep, userId } = user
const classes = useStyles();
const theme = useTheme();
const [activeStep, setActiveStep] = React.useState(lastActiveStep || 0);
React.useEffect(() => {
async function updateActiveStep() {
// this is just pseudo code - whatever your endpoint looks like
await window.fetch('/yourEndpoint/:userId', {
method: 'PUT',
body: JSON.stringify({activeStep})
})
}
updateActiveStep()
}, [activeStep])
/* ... rest of your component * /
}
我想保存 Mobile Stepper 的进度状态,这样当用户注销时,用户可以从他离开的地方继续。如果进度条填充了 2%,那么下次用户登录时,他应该从 2% 恢复,而不是从 0 恢复。 这是代码:
import React, { useState, useReducer, useEffect } from "react";
import { Button, Typography, Grid, CircularProgress, Paper } from '@mui/material/';
import guardianOptions from '../../../constants/guardianOptions.js';
import studentClasses from '../../../constants/studentClasses.js';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
import StepLabel from '@mui/material/StepLabel';
import MobileStepper from '@mui/material/MobileStepper';
import StepContent from '@mui/material/StepContent';
import { makeStyles, withStyles, createStyles } from '@mui/styles';
import { purple } from '@mui/material/colors';
import TextField from '@mui/material/TextField';
import useStyles from './styles';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormHelperText from '@mui/material/FormHelperText';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
const User= (props) => {
const { activeStep: lastActiveStep, userId } = props;
const classes = useStyles();
const [guardianType, setGuardianType] = useState(0);
const [activeStep, setActiveStep] = useState(lastActiveStep || 0);
const [guardianRelationOptions, setGuardianRelationOptions] = useState(0);
const [guardianDetailsForm, setGuardianDetailsForm] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{}
);
const [studentDetailsForm, setStudentDetailsForm] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{ s_firstName: '', s_lastName: '', s_age: '', s_class: '' }
);
React.useEffect(() => {
async function updateActiveStep() {
// this is just pseudo code - whatever your endpoint looks like
await window.fetch('http://localhost:8080/api/user/:userId', {
method: 'PUT',
body: JSON.stringify({activeStep})
})
}
updateActiveStep()
}, [activeStep]);
function getSteps(){
return [<b style={{color:'purple'}}>'Personal Details'</b>,
<b style={{color:'purple'}}>'Relation'</b>,
<b style={{color:'purple'}}>'Guardian Details'</b>];
}
const steps = getSteps();
function onGuardianTypeChangeChange(event) {
// setAge(event.target.value);
setGuardianType(event.target.value);
let _guardianRelationOptions = guardianOptions.find(options => options.value === event.target.value);
setGuardianRelationOptions(_guardianRelationOptions.relationships);
}
const handleGuardianDeatilsInput = evt => {
const name = evt.target.name;
const newValue = evt.target.value;
setGuardianDetailsForm({ [name]: newValue });
};
const handleGuardianDetailsSubmit = evt => {
evt.preventDefault();
let data = { guardianDetailsForm };
props.onGuardianDetails(guardianDetailsForm)
console.log(data + "new user");
// console.log( props.onGuardianDetails(guardianDetailsForm) + "gana bajao");
setActiveStep((prevActiveStep) => prevActiveStep+1);
setGuardianDetailsForm();
}
function getStepContent(step) {
switch (step) {
case 0: if (!props.user.s_firstName) {
return (<div>
<form id ="form-step0" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<TextField
id="outlined-basic"
name="s_firstName"
label="First Name"
variant="outlined"
defaultValue={guardianDetailsForm.s_firstName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-basic"
name="s_lastName"
label="Last Name"
variant="outlined"
defaultValue={guardianDetailsForm.s_lastName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-number"
label="Age"
name="s_age"
defaultValue={guardianDetailsForm.s_age}
type="number"
InputLabelProps={{
shrink: true,
}}
onChange={handleGuardianDeatilsInput}
variant="outlined"
/>
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Class</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={guardianDetailsForm.s_class}
onChange={handleGuardianDeatilsInput}
label="Class"
name="s_class"
>
{studentClasses.map(c =>
<MenuItem key={c.value} value={c.value}>{c.name}</MenuItem>
)}
</Select>
{/* <Button variant="contained" type="submit" color="primary" >NEXT</Button> */}
</FormControl>
</form>
</div> )}
;
case 1: if (!props.user.g_relationship) {
return ( <div>
<form id="form-step1" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Relationship</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
onChange={onGuardianTypeChangeChange}
label="Relationship"
>
{guardianOptions.map(type =>
<MenuItem key={type.value} value={type.value}>{type.name}</MenuItem>
)}
</Select>
</FormControl>
{guardianRelationOptions ?
<FormControl variant="outlined" className={classes.formControl}
sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-outlined-label">Relation</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
// value={age}
name="g_relationship"
value={guardianDetailsForm.g_relationship}
onChange={handleGuardianDeatilsInput}
label="Relation"
>
{guardianRelationOptions.map(type =>
<MenuItem key={type.value} value={type.value}>{type.name}</MenuItem>
)}
</Select>
</FormControl> : null
}
{!g_relationship} onClick={() => props.onGuardianDetails({g_relationship})}>NEXT</Button> */}
{/* <Button variant="contained" color="primary" type="submit">NEXT</Button> */}
</form>
</div> )}
;
case 2:
return ( <div>
<form id="form-step2" className={classes.root} onSubmit={handleGuardianDetailsSubmit} noValidate autoComplete="off">
<TextField
id="outlined-basic"
name="g_firstName"
label="First Name"
variant="outlined"
defaultValue={guardianDetailsForm.g_firstName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-basic"
name="g_lastName"
label="Last Name"
variant="outlined"
defaultValue={guardianDetailsForm.g_lastName}
onChange={handleGuardianDeatilsInput} />
<TextField
id="outlined-number"
label="Age"
name="g_age"
defaultValue={guardianDetailsForm.g_age}
type="number"
InputLabelProps={{
shrink: true,
}}
onChange={handleGuardianDeatilsInput}
variant="outlined"
/>
</form>
</div>)
;
default:
return 'welcome lets fill the progress.' ;
}
}
return (
<div className={classes.root} align="center">
<div className = {classes.actionsContainer}>
<Paper square elevation={0}>
<Typography>{getStepContent(activeStep)}</Typography>
</Paper>
<MobileStepper
variant="progress"
steps= {4}
position="bottom"
activeStep={activeStep}
sx={{ minWidth: 400, flexGrow: 1 }}
nextButton={
<>
<Button size="small" onClick={handleGuardianDetailsSubmit} type="submit"
form={`form-step${activeStep}`}>
{activeStep === steps.length-1? 'Finish' : 'Next'}
</Button>
</>
}
/>
</div>
</div>
);
}
export default User;
如果用户刷新或重新加载页面,他应该从他离开的地方看到进度。
@Tanya
所以你是说你的用户可以授权。发生这种情况时,您会收到有关用户的任何数据吗?您可以通过 POST 或 PUT 请求更新用户数据吗?如果是这样,我将使用此数据存储活动步骤。
假设您有一些在用户登录时收到的用户数据:
// user - user data
export default function BuildAdStepper({user}) {
const { activeStep: lastActiveStep, userId } = user
const classes = useStyles();
const theme = useTheme();
const [activeStep, setActiveStep] = React.useState(lastActiveStep || 0);
React.useEffect(() => {
async function updateActiveStep() {
// this is just pseudo code - whatever your endpoint looks like
await window.fetch('/yourEndpoint/:userId', {
method: 'PUT',
body: JSON.stringify({activeStep})
})
}
updateActiveStep()
}, [activeStep])
/* ... rest of your component * /
}