'Readonly <{}>'类型中不存在'ValueChanging'

Ian*_*nck 12 typescript reactjs

我正在尝试在React中为SurveyJS中实现的调查实现一个处理程序.这适用于多项选择题,可能有"无以上"或"不愿回答"等答案.如果选择了其中一个答案,则应清除所有其他答案,如果选择了不同的答案,则应清除这些复选框.我对其中任何一个单独做得很好,但是对于存在两个选项的问题都有问题,特别是在两个特殊选项之间来回切换时.

我认为发生的是当一个答案触发处理程序并取消选中另一个复选框时,它会再次触发处理程序.我的解决方案是设置一个状态,指示处理程序何时处于此过程的中间,而不是在此时再次执行.

我在这里得到了一个JS解决方案:https://github.com/surveyjs/editor/issues/125 - 以下是我尝试将其转换为React.(只包括代码的相关部分.)

但是,在编译时,它会出现以下错误:

[at-loader]中的错误./src/components/Sur​​vey/SurveyContainer.tsx:55:19 TS2339:属性'ValueChanging'在'Readonly <{}>'类型中不存在.

我找不到任何有关此特定错误的信息.其他对状态的引用(即我设置它的地方)正在工作.为什么我不能读它?

谢谢!

零件:

import * as React from 'react';
import { Component } from 'react';
import { Survey, surveyStrings } from 'survey-react';
import 'whatwg-fetch';
import Marked from '../Marked';
import * as style from './style';

interface Props {
  surveyJson: object;
  complete: boolean;
  resultMarkdown: string;
  surveyTitle: string;
  sendSurveyAnswers: (answers: object[]) => void;
  noneOfTheAboveHandler: (survey: object, options: object) => void;
}

Survey.cssType = 'standard';
surveyStrings.progressText = '{0}/{1}';
surveyStrings.emptySurvey = '';

export default class SurveyComponent extends Component<Props, {}> {
  render() {
    const { surveyJson, sendSurveyAnswers, complete, surveyTitle, resultMarkdown, noneOfTheAboveHandler } = this.props;
    return (
      <style.Wrapper>
         { surveyJson && (!complete) &&
          <style.SurveyWrapper>
            <style.SurveyTitle>{ surveyTitle }</style.SurveyTitle>
            <style.Survey>
              <Survey
                onValueChanged={ noneOfTheAboveHandler }
                css={ style.surveyStyles }
                json={ surveyJson }
                onComplete={ sendSurveyAnswers }
              />
            </style.Survey>
          </style.SurveyWrapper>
         }
         { complete &&
         <style.Results>
           <Marked content={resultMarkdown} />
         </style.Results>
         }
      </style.Wrapper>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

容器:

import * as React from 'react';
import { Component } from 'react';
import { connect } from 'react-redux';
import SurveyComponent from './SurveyComponent';

interface Props {
  id: string;
  surveyJson: object;
  complete: boolean;
  resultMarkdown: string;
  surveyTitle: string;
  getSurveyQuestions: (id: string) => void;
  sendSurveyAnswers: (answers: object[]) => void;
  noneOfTheAboveHandler: (survey: object, options: object) => void;
  clearSurvey: () => void;
}

class SurveyContainer extends Component<Props, {}> {
  constructor(props) {
    super(props);
    this.state = { ValueChanging: false };
  }

  componentDidMount() {
    this.noneOfTheAboveHandler = this.noneOfTheAboveHandler.bind(this);
    this.props.getSurveyQuestions(this.props.id);
  }

  specialValueSelected(options, specialValue) {
    const { question } = options;
    const prevValue = question.prevValue;
    const index = options.value.indexOf(specialValue);
    this.setState({ ValueChanging: true });
    //has special value selected
    if(index > -1) {
      //special value was selected before
      if(prevValue.indexOf(specialValue) > -1) {
        var value = question.value;
        value.splice(index, 1);
        question.value = value;
      } else {
        //special value select just now
        question.value = [specialValue];
      }
    }
    this.setState({ ValueChanging: false });
    return index > -1;
  }

  noneOfTheAboveHandler(survey, options) {
    const none = 'NA';
    const preferNotToAnswer = 'PN';
    const { question } = options;

    if(this.state.ValueChanging) {
      return;
    }

    if (!question || question.getType() !== 'checkbox') {
      return;
    }

    if (!question.prevValue || !options.value) {
      question.prevValue = options.value;
      return;
    }

    if (!this.specialValueSelected(options,none)) {
      this.specialValueSelected(options,preferNotToAnswer);
    }

    question.prevValue = options.value;
  }

  componentWillUnmount() {
    this.props.clearSurvey();
  }

  render() {
    return (
      <SurveyComponent
        noneOfTheAboveHandler={this.noneOfTheAboveHandler}
        {...this.props}
      />
    );
  }
}

const mapStateToProps = (state, ownProps) => ({
  surveyJson: state.survey.json,
  answers: state.survey.answers,
  resultMarkdown: state.survey.resultMarkdown,
  complete: state.survey.complete,
  surveyTitle: state.page && state.page.data ? state.page.data.title : ''
});

const mapDispatchToProps = dispatch => ({
  getSurveyQuestions: id => dispatch({ type: 'GET_SURVEY_QUESTIONS', id }),
  sendSurveyAnswers: answers => dispatch({ type: 'SEND_SURVEY_ANSWERS', answers: answers.data }),
  clearSurvey: () => dispatch({ type: 'CLEAR_SURVEY' })
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SurveyContainer);
Run Code Online (Sandbox Code Playgroud)

Obl*_*sys 24

最可能的原因是您没有在其类定义中指定组件状态的类型,因此默认为{}.您可以通过声明类型的props和state的接口并将它们作为类型参数提供给React.Component来修复它:

interface MyComponentProps { /* declare your component's props here */ }
interface MyComponentState { ValueChanging :  boolean }

class MyComponent extends React.Component<MyComponentProps, MyComponentState> {
  constructor(props) {
  ...
Run Code Online (Sandbox Code Playgroud)

您可以直接在<和之间提供类型>,但使用接口通常会产生更易读的代码并促进重用.为了防止与组件混淆,对于props和state上的属性使用小写标识符也是一个好主意.