reactjs - 如何在 Stepper - Material UI 中实现条件渲染?React.Js 步骤进度条
问题描述
上下文:我需要一张标题为:“您的个人资料完成度为 16%!”的卡片,以及一个包含 6 个步骤(圆圈)的步骤进度条,每个步骤背后都有一个必须满足才能激活的条件。我一直呆在这里,因为我找到的所有东西都是按钮,我不需要一个,我需要使用条件语句。
例如:
- 对于第 1 圈,您必须经过身份验证;
- 对于第 2 圈,您必须完成测验;
- 对于第 3 圈,您必须有个人资料图片;
我希望这个步骤栏不是线性的,例如,如果有个人资料图片,但我没有参加测验,那么第 3 个圆圈将是完整的。
这个 Stepper 将连接到 Redux。
const mapStateToProps = state => {
const { profile, user } = state.Login;
const quiz = get( profile,'userData.quiz' );
const profilePicture = get( profile,'userData.profilePictureId' );
return {
profile,
isAuthenticated: !!user.accessToken,
quiz,
profilePicture
};
};
const mapDispatchToProps = {
action
};
我的代码基础取自 Material -Ui:
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step';
import StepButton from '@material-ui/core/StepButton';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
button: {
marginRight: theme.spacing(1),
},
backButton: {
marginRight: theme.spacing(1),
},
completed: {
display: 'inline-block',
},
instructions: {
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
},
}));
function getSteps() {
return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
}
function getStepContent(step) {
switch (step) {
case 0:
return 'Step 1: Select campaign settings...';
case 1:
return 'Step 2: What is an ad group anyways?';
case 2:
return 'Step 3: This is the bit I really care about!';
default:
return 'Unknown step';
}
}
export default function HorizontalNonLinearAlternativeLabelStepper() {
const classes = useStyles();
const [activeStep, setActiveStep] = React.useState(0);
const [completed, setCompleted] = React.useState(new Set());
const [skipped, setSkipped] = React.useState(new Set());
const steps = getSteps();
const totalSteps = () => {
return getSteps().length;
};
const isStepOptional = (step) => {
return step === 1;
};
const handleSkip = () => {
if (!isStepOptional(activeStep)) {
// You probably want to guard against something like this
// it should never occur unless someone's actively trying to break something.
throw new Error("You can't skip a step that isn't optional.");
}
setActiveStep((prevActiveStep) => prevActiveStep + 1);
setSkipped((prevSkipped) => {
const newSkipped = new Set(prevSkipped.values());
newSkipped.add(activeStep);
return newSkipped;
});
};
const skippedSteps = () => {
return skipped.size;
};
const completedSteps = () => {
return completed.size;
};
const allStepsCompleted = () => {
return completedSteps() === totalSteps() - skippedSteps();
};
const isLastStep = () => {
return activeStep === totalSteps() - 1;
};
const handleNext = () => {
const newActiveStep =
isLastStep() && !allStepsCompleted()
? // It's the last step, but not all steps have been completed
// find the first step that has been completed
steps.findIndex((step, i) => !completed.has(i))
: activeStep + 1;
setActiveStep(newActiveStep);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleStep = (step) => () => {
setActiveStep(step);
};
const handleComplete = () => {
const newCompleted = new Set(completed);
newCompleted.add(activeStep);
setCompleted(newCompleted);
/**
* Sigh... it would be much nicer to replace the following if conditional with
* `if (!this.allStepsComplete())` however state is not set when we do this,
* thus we have to resort to not being very DRY.
*/
if (completed.size !== totalSteps() - skippedSteps()) {
handleNext();
}
};
const handleReset = () => {
setActiveStep(0);
setCompleted(new Set());
setSkipped(new Set());
};
const isStepSkipped = (step) => {
return skipped.has(step);
};
function isStepComplete(step) {
return completed.has(step);
}
return (
<div className={classes.root}>
<Stepper alternativeLabel nonLinear activeStep={activeStep}>
{steps.map((label, index) => {
const stepProps = {};
const buttonProps = {};
if (isStepOptional(index)) {
buttonProps.optional = <Typography variant="caption">Optional</Typography>;
}
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={label} {...stepProps}>
<StepButton
onClick={handleStep(index)}
completed={isStepComplete(index)}
{...buttonProps}
>
{label}
</StepButton>
</Step>
);
})}
</Stepper>
<div>
{allStepsCompleted() ? (
<div>
<Typography className={classes.instructions}>
All steps completed - you're finished
</Typography>
<Button onClick={handleReset}>Reset</Button>
</div>
) : (
<div>
<Typography className={classes.instructions}>{getStepContent(activeStep)}</Typography>
<div>
<Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
Back
</Button>
<Button
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
>
Next
</Button>
{isStepOptional(activeStep) && !completed.has(activeStep) && (
<Button
variant="contained"
color="primary"
onClick={handleSkip}
className={classes.button}
>
Skip
</Button>
)}
{activeStep !== steps.length &&
(completed.has(activeStep) ? (
<Typography variant="caption" className={classes.completed}>
Step {activeStep + 1} already completed
</Typography>
) : (
<Button variant="contained" color="primary" onClick={handleComplete}>
{completedSteps() === totalSteps() - 1 ? 'Finish' : 'Complete Step'}
</Button>
))}
</div>
</div>
)}
</div>
</div>
);
}
我尝试了一个愚蠢的解决方案,但它不能正常工作:
function StepNavigation( isAuthenticated, quiz, profile, step, profilePicture ) {
const classes = useStyles();
const steps = getSteps();
if (isAuthenticated) {
step = 1
} else
{ step = 0
};
console.log(step);
if (bodyShape) {
step = 2
} else
{ step = 0
}; console.log(step);
...
<Stepper alternativeLabel activeStep={step} ...>
我需要你的帮助,我为我的错误感到抱歉!:(
解决方案
推荐阅读
- gradle - 如何访问分发存档
- java - JavaFX:未设置位置
- java - 扫描器在 for 循环中,在获取任何输入之前循环一次
- .net - 如何使用 Visual Studio 在 Excel 中的单元格中创建超链接?
- html - Firefox 验证不会阻止用户输入无效输入
- c# - 设计模式:如何为未知的未来组合建模?
- sql - 如何在值列表中返回在顶点中显示值
- python-3.x - 将 sympy.core.symbol.Symbol 转换为浮点数
- cloud-foundry - SAP Cloud Platform (Cloud Foundry) 上的 JCO 问题
- c# - Leetcode testing Linked list