Преобразование Material-UI в класс в реаги - PullRequest
0 голосов
/ 20 сентября 2019

Я пытаюсь использовать компонент 'Stepper реагирующий материал-ui , но мне трудно использовать его классным способом, а не функционировать, как в предварительном просмотре.

Вот то, что у меня есть, и оно загружается, но с некоторыми проблемами:

  1. Появляется текст «неизвестный шаг», означающий, что функция «getStepContent» невызывается правильно
  2. Каждый раз, когда я нажимаю кнопку «Далее», появляется сообщение об ошибке: «Невозможно прочитать свойство» имеет «неопределенное», похоже, что почти все мои вызовы функций перепутаны ...

Вот мой код:

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&apos;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 вместо классафункции ..

Спасибо за помощь!

1 Ответ

0 голосов
/ 20 сентября 2019

Я думаю, что вы стираете 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 будут вашим компонентом, как вы ожидаете.

Однако, если вместо этого выdo:

const {handleNext} = this;
handleNext();

Ссылка this может не соответствовать ожидаемой причине, поскольку метод не был вызван как метод в вашем компоненте.Он был вызван как отдельная функция, отделенная от вашего компонента.И это именно то, что происходит, когда вы передаете обработчик события другому компоненту.Внутри дочернего компонента (например, кнопки) ваш обработчик представляет собой просто функцию, переданную в виде пропеллера, отсоединенного от вашего компонента:

// inside the button component
const {onClick} = this.props;
onClick(); // no scope; detached from your component

Есть несколько способов исправить это, но два наиболееПроще говоря:

  1. Объявить новую функцию, которая вызывает обработчик компонента:
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
})
...