gpt4 book ai didi

javascript - 如何使用 React 管理多步骤表单?

转载 作者:行者123 更新时间:2023-11-29 15:54:56 26 4
gpt4 key购买 nike

这是我的多步表单的代码:

import clsx from 'clsx';
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles, withStyles } from '@material-ui/styles';
import Step from '@material-ui/core/Step';
import Stepper from '@material-ui/core/Stepper';
import StepLabel from '@material-ui/core/StepLabel';
import StepConnector from '@material-ui/core/StepConnector';
import { Container, Row, Col, Button } from 'react-bootstrap';

import Description from '@material-ui/icons/Description';
import AccountCircle from '@material-ui/icons/AccountCircle';
import DirectionsCar from '@material-ui/icons/DirectionsCar';

import Step1 from '../components/Step1';
import Step2 from '../components/Step2';
import Step3 from '../components/Step3';

const styles = () => ({
root: {
width: '90%',
},
button: {
marginRight: '0 auto',
},
instructions: {
marginTop: '0 auto',
marginBottom: '0 auto',
},
});

const ColorlibConnector = withStyles({
alternativeLabel: {
top: 22,
},
active: {
'& $line': {
backgroundColor: '#00b0ff',
},
},
completed: {
'& $line': {
backgroundColor: '#00b0ff',
},
},
line: {
height: 3,
border: 0,
backgroundColor: '#eaeaf0',
borderRadius: 1,
},
})(StepConnector);

const useColorlibStepIconStyles = makeStyles({
root: {
backgroundColor: '#ccc',
zIndex: 1,
color: '#fff',
width: 50,
height: 50,
display: 'flex',
borderRadius: '50%',
justifyContent: 'center',
alignItems: 'center',
},
active: {
backgroundColor: '#00b0ff',
boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)',
},
completed: {
backgroundColor: '#00b0ff',
},
});

function ColorlibStepIcon(props) {
const classes = useColorlibStepIconStyles();
const { active, completed } = props;

const icons = {
1: <AccountCircle />,
2: <DirectionsCar />,
3: <Description />,
};

return (
<div
className={clsx(classes.root, {
[classes.active]: active,
[classes.completed]: completed,
})}
>
{icons[String(props.icon)]}
</div>
);
}

function getSteps() {
return ['Dati Assicurato', 'Dati Veicolo', 'Dati Assicurazione'];
}

function getStepContent(step) {
switch (step) {
case 0:
return <Step1/>;
case 1:
return <Step2/>;
case 2:
return <Step3/>;;
default:
return 'Unknown step';
}
}

class HorizontalLinearStepper extends React.Component {

constructor(props) {
super(props);
this.state = {
activeStep: 0,
agencyData: {}
};
}

static propTypes = {
classes: PropTypes.object,
};

isStepOptional = step => {
return step === 1;
};

handleNext = () => {
const { activeStep } = this.state;
this.setState({
activeStep: activeStep + 1,
});
};

handleBack = () => {
const { activeStep } = this.state;
this.setState({
activeStep: activeStep - 1,
});
};

handleReset = () => {
this.setState({
activeStep: 0,
});
};

logout = () => {
localStorage.clear();
this.props.history.push('/');
}

render() {
const { classes } = this.props;
const steps = getSteps();
const { activeStep } = this.state;

return (
<Container fluid>
<div className={classes.root}>
<Stepper alternativeLabel activeStep={activeStep} connector={<ColorlibConnector />}>
{steps.map((label, index) => {
const props = {};

return (
<Step key={label} {...props}>
<StepLabel StepIconComponent={ColorlibStepIcon}>{label}</StepLabel>
</Step>
);
})}
</Stepper>

<div>
{activeStep === steps.length ? (
<div style={{textAlign: 'center'}}>
<h1 style={{textAlign: 'center', paddingTop: 100, color: '#7fc297'}}>
TERMINATO
</h1>
<h4 style={{textAlign: 'center', paddingTop: 50}}>
Tutti gli step sono stati completati con successo!
</h4>
<h4 style={{textAlign: 'center'}}>
Procedi con la generazione del QR Code.
</h4>
<Row style={{marginTop: '40px'}} className='justify-content-center align-items-center text-center'>
<Col md={{span: 3}}>
<Button
style={{borderRadius: 30, borderWidth: 0, height: 50, width: 150, backgroundColor: '#f32a19', borderColor: '#f32a19'}}
disabled={activeStep === 0}
onClick={this.handleReset}
>
Annulla
</Button>
</Col>
<Col md={{span: 3}}>
<Button
style={{borderRadius: 30, borderWidth: 0, height: 50, width: 150, backgroundColor: '#00b0ff'}}
onClick={() => console.log('Click')}
>
Procedi
</Button>
</Col>
</Row>
</div>
) :
(
<Container style={{}}>
<h2 className={classes.instructions}>{getStepContent(activeStep)}</h2>
<Row className='justify-content-center align-items-center text-center'>
<Col md={{span: 3}}>
<Button
style={{marginTop: 10, backgroundColor: 'gold', borderRadius: 30, borderWidth: 0, height: 50, width: 150}}
disabled={activeStep === 0}
onClick={this.handleBack}
>
Indietro
</Button>
</Col>
<Col md={{span: 3}}>
{
activeStep === steps.length - 1 ?
<Button
style={{marginTop: 10, borderRadius: 30, borderWidth: 0, height: 50, width: 150, backgroundColor: '#7fc297'}}
onClick={this.handleNext}
>
Finito
</Button>
:
<Button
style={{marginTop: 10, backgroundColor: '#00b0ff', borderRadius: 30, borderWidth: 0, height: 50, width: 150}}
onClick={this.handleNext}
>
Avanti
</Button>
}
</Col>
</Row>
</Container>
)}
</div>
</div>
</Container>
);
}
}

export default withStyles(styles)(HorizontalLinearStepper);

它由三个步骤组成,在每个步骤中我都要求提供很多数据。

这是其中一个Step的代码(都是一样的,不同的是输入框的内容):

import React from 'react';
import { Container, Row, Col, Form } from 'react-bootstrap';

export default function Step2(props) {

return(
<Container>
<Row style={{marginTop: '30px'}} className='h-100 justify-content-center align-items-center'>
<Col md={{ span: 6 }} className='text-center my-auto'>
<h3 style={{marginBottom: '1rem'}}>Dati Veicolo</h3>
<Form>
<Form.Row>
<Form.Group as={Col}>
<Form.Control
type='text'
placeholder='Marca'
required
/>
</Form.Group>
<Form.Group as={Col}>
<Form.Control
type='text'
placeholder='Targa'
required
/>
</Form.Group>
</Form.Row>
<Form.Group>
<Form.Control
type='text'
placeholder='Paese immatricolazione'
required
/>
</Form.Group>
<h6 style={{marginBottom: '1rem'}}>Possiede un rimorchio?</h6>
<Form.Group>
<Form.Control
type='text'
placeholder='Targa'
/>
</Form.Group>
<Form.Group>
<Form.Control
type='text'
placeholder='Paese immatricolazione'
/>
</Form.Group>
</Form>
</Col>
</Row>
</Container>
);
}

我需要做的是在用户进入下一步之前检查每一步是否有错误,以便他们只有在正确完成第一步的情况下才能开始填写表单的第二步,并且很快 ...我如何逐步进行此检查?

此外,我如何收集我在表单的主要部分中要求的所有数据,以便在用户完成整个表单后我可以处理所有这些数据?

在此link有例子

最佳答案

你的组件层次结构看起来不错,我想添加一件事来把东西放在一起,比如你可以像这样在主要组件状态中创建一个数组的步骤

class Main extends React.Component{
state = {
...OTHER_STATE_PROPERTIES,
activeStep: 0 | 1| 2,
steps: [{
name: 'step-name',
icon: 'icon-name',
content: Form1 | Form2 | Form3, // this is optional, you can use getContent too
data: {}
}]
}


// pass this function as prop to every Form Component
// We will talk about this function soon
handleStepSubmit = (stepIndex, data) => {
this.setState((prevState) => ({
...prevState,
activeIndex: prevState.activeIndex + 1,
steps: prevState.map((step, index) => {
if(stepIndex !== index){
return step;
}
return {
...step,
data
}
})
}))
}
//... Other stuff

}

现在每个 Form 都应该有自己的 state(这样只有表单在输入更改时重新呈现)和 form,其中您可以处理输入并验证它们并使用 Prop 将其发送到父组件步骤,因此我们需要在父组件中添加一个函数。 handleStepSubmit 函数只会在 onSubmit 调用 form

时验证数据后调用

如何验证数据由你决定,你可以使用

默认输入属性,如

  1. 需要
  2. 数量的最小值,最大值
  3. 输入(电子邮件)
  4. 模式

使用 JS 逻辑验证状态

使用yup

使用Formik是的

这是我更喜欢的,通过使用 formik 你不必担心 onChangevalidation 和更多的东西,你可以提供它 validate prop 你可以自己编写验证逻辑或者 validationSchema prop 应该只给出 yup schema,如果 onSubmit 如果验证失败则不允许触发,你可以如果表单很简单,还可以输入属性。我们必须在 onSubmit

上调用 handleStepSubmit

P.S.: 它维护一个本地状态

我们有什么

在第0步我们将有

// I am omitting other stuff for understanding
state:{
activeStep: 0,
steps: [
{data: {}},
{data: {}},
{data: {}},
]
}

当用户提交表格 1 时,我们将拥有

// I am omitting other stuff for understanding
state:{
activeStep: 1,
steps: [
{data: formOneData},
{data: {}},
{data: {}},
]
}

现在,当 activeStep 为 3 时,您将拥有状态中的所有经过验证的数据,Horray!!举手击掌!如果需要,您还可以在进一步的步骤中获取之前步骤中的数据,因为我们的父组件状态中都有这些数据。

示例:

Edit formik-example

关于javascript - 如何使用 React 管理多步骤表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58863744/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com