我正在尝试使用'Stepper' react material-ui组件,但是我很难以类的方式使用它,而不是像它们在预览中那样使用。
这是我到目前为止所拥有的,它确实可以加载,但是存在一些问题:
这是我的代码:
import React, { Component } from "react";
import "./CharacterCreate.css";
import PropTypes from 'prop-types';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Typography from '@material-ui/core/Typography';
import Box from '@material-ui/core/Box';
import { makeStyles } from '@material-ui/core/styles';
import Stepper from '@material-ui/core/Stepper';
import Step from '@material-ui/core/Step';
import StepLabel from '@material-ui/core/StepLabel';
import Button from '@material-ui/core/Button';
export default class CharacterCreate extends Component {
constructor(props) {
super(props);
this.state = {
activeStep: 0,
skipped :new Set()
};
this.handleNext = this.handleNext.bind(this);
this.isStepSkipped = this.isStepSkipped.bind(this);
}
getSteps() {
return ['Select campaign settings', 'Create an ad group', 'Create an ad'];
}
getStepContent(step) {
switch (step) {
case 0:
return 'Select campaign settings...';
case 1:
return 'What is an ad group anyways?';
case 2:
return 'This is the bit I really care about!';
default:
return 'Unknown step';
}
}
isStepOptional(step) {
return step === 1;
}
isStepSkipped(step) {
return this.state.skipped.has(step);
}
handleNext() {
let newSkipped = this.skipped;
if (this.isStepSkipped(this.activeStep)) {
newSkipped = new Set(newSkipped.values());
newSkipped.delete(this.activeStep);
}
this.setState({activeStep: prevActiveStep => prevActiveStep + 1})
this.setState({skipped: this.skipped});
}
handleBack() {
this.setState({activeStep: prevActiveStep => prevActiveStep - 1})
}
handleSkip() {
if (!this.isStepOptional(this.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.");
}
this.setState({activeStep: prevActiveStep => prevActiveStep + 1})
this.setSkipped(prevSkipped => {
const newSkipped = new Set(prevSkipped.values());
newSkipped.add(this.activeStep);
return newSkipped;
});
}
handleReset() {
this.setState({activeStep: 0})
}
render() {
const steps = this.getSteps();
return (
<div className="root">
<Stepper activeStep={this.activeStep}>
{steps.map((label, index) => {
const stepProps = {};
const labelProps = {};
if (this.isStepOptional(index)) {
labelProps.optional = <Typography variant="caption">Optional</Typography>;
}
if (this.isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step key={label} {...stepProps}>
<StepLabel {...labelProps}>{label}</StepLabel>
</Step>
);
})}
</Stepper>
<div>
{this.activeStep === steps.length ? (
<div>
<Typography className="instructions">
All steps completed - you're finished
</Typography>
<Button onClick={this.handleReset} className="button">
Reset
</Button>
</div>
) : (
<div>
<Typography className="instructions">{this.getStepContent(this.activeStep)}</Typography>
<div>
<Button disabled={this.activeStep === 0} onClick={this.handleBack} className="button">
Back
</Button>
{this.isStepOptional(this.activeStep) && (
<Button
variant="contained"
color="primary"
onClick={this.handleSkip}
className="button"
>
Skip
</Button>
)}
<Button
variant="contained"
color="primary"
onClick={this.handleNext}
className="button"
>
{this.activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</div>
</div>
)}
</div>
</div>
);
}
}
我知道很多,但是我只是想将Material-ui网站中的示例代码用作类而不是函数。
谢谢您的帮助!
答案 0 :(得分:0)
我认为您是在这里清除this.state.skipped
,因为this.skipped
似乎没有在任何地方声明。
this.setState({skipped: this.skipped});
此呼叫后,this.state.skipped
是undefined
,因此呼叫this.state.skipped.has(...)
会爆炸。
我怀疑您打算使用this.state.skipped
。
另一个麻烦源可能是范围问题,它是由于单击处理程序的声明和附加方式引起的,例如onClick={this.handleNext}
。
TLDR:请尝试使用onClick={() => this.handleNext()}
。
在javascript中,方法调用中的范围(this
所指的范围)通常设置为调用它的对象。
因此,如果您调用this.handleNext()
,则在this
中对handleNext
的引用将成为您的组件。
但是,如果您这样做,则:
const {handleNext} = this;
handleNext();
this
引用可能不是您期望的,因为该方法未在组件上作为方法调用。它是作为独立功能调用的,与组件分离。这实际上是将事件处理程序传递给另一个组件时发生的情况。在子组件(例如按钮)内部,处理程序只是作为prop传入的一个函数,与组件分离:
// inside the button component
const {onClick} = this.props;
onClick(); // no scope; detached from your component
有几种方法可以解决此问题,但最简单的两种方法是:
onClick={ () => this.handleNext() }
handleNext() {
let newSkipped = this.skipped;
...
执行以下操作:
handleNext = () => {
let newSkipped = this.skipped;
希望这会有所帮助。抱歉,太久了。试一试,让我知道。
旁注:您可以在一次通话中完成这两项操作
this.setState({activeStep: prevActiveStep => prevActiveStep + 1})
this.setState({skipped: this.skipped});
this.setState({
activeStep: prevActiveStep => prevActiveStep + 1,
skipped: this.state.skipped
})