添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are you requesting a feature, reporting a bug or asking a question?

Question

What is the current behavior?

state grows exponentially each time i choose an option in my survey.

What is the expected behavior?

setState is called once every time an option is updated without interfering with the survey.

Test code

    onValueChanged = (model) => (e) => {
        fetch('http://localhost:5000/api/post', {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            body: JSON.stringify(model.data)
        }).then(json => {
            this.setState({githubData: json});

Specify your

  • browser: Firefox
  • surveyjs platform: React
  • surveyjs version: Latest
  • I am trying to call my api everytime a user selects an option or changes it. With that information i am trying to update a sidebar. But if i call setstate in onvaluechanged first the state grows exponentially and second the options don't reset. So if normally i can choose one of three options, with setstate enabled i can choose all three. Any ideas?

    I'm sorry it's in React. I was coming of a 10 hour marathon without access to the docs and was a little bit tired. xD Here is the minimal code.

    import React, {Component} from "react";
    import * as Survey from "survey-react";
    import "survey-react/survey.css";
    import SurveyEditor from "./SurveyEditor";
    import logo from "./logo.svg";
    import "./App.css";
    import "bootstrap/dist/css/bootstrap.css";
    import StickyBox from "react-sticky-box";
    import "./style.css";
    import "jquery-ui/themes/base/all.css";
    import "nouislider/distribute/nouislider.css";
    import "select2/dist/css/select2.css";
    import "bootstrap-slider/dist/css/bootstrap-slider.css";
    import "jquery-bar-rating/dist/themes/css-stars.css";
    import $ from "jquery";
    import "jquery-ui/ui/widgets/datepicker.js";
    import "select2/dist/js/select2.js";
    import "jquery-bar-rating";
    import * as widgets from "surveyjs-widgets";
    widgets.icheck(Survey, $);
    widgets.select2(Survey, $);
    widgets.inputmask(Survey);
    widgets.jquerybarrating(Survey, $);
    widgets.jqueryuidatepicker(Survey, $);
    widgets.nouislider(Survey);
    widgets.select2tagbox(Survey, $);
    widgets.signaturepad(Survey);
    widgets.sortablejs(Survey);
    widgets.ckeditor(Survey);
    widgets.autocomplete(Survey, $);
    widgets.bootstrapslider(Survey);
    class App extends Component {
        json = {
            "pages": [
                    "name": "page1",
                    "elements": [
                            "type": "radiogroup",
                            "name": "datastructure",
                            "title": "Which data structure/study design does your dataset have?",
                            "isRequired": true,
                            "choices": [
                                    "value": "cross_sectional_study",
                                    "text": "A cross-sectional study: (also known as a cross-sectional analysis, transverse study, prevalence study) is a type of observational study that analyzes data from a population, or a representative subset, at a specific point in time�that is, cross-sectional data. "
                                    "value": "panel_data",
                                    "text": "Panel data: In statistics and econometrics, panel data or longitudinal data[1][2] are multi-dimensional data involving measurements over time. Panel data contain observations of multiple phenomena obtained over multiple time periods for the same firms or individuals. (Paired Data) "
                                    "value": "time_series",
                                    "text": "Time series data: A time series is a series of data points indexed (or listed or graphed) in time order. (more than 100 measurments over time) "
        onValueChanged = (model) => (e) => {
            this.setState({
                githubData: model.data
        constructor(props) {
            super(props);
            this.state = {
                requestFailed: false,
                githubData: {},
        componentWillMount() {
            import("icheck");
            //fetch('http://localhost:5000/')
            //this.getData();
            window["$"] = window["jQuery"] = $;
        onComplete(result) {
            console.log("Complete! " + result);
        render() {
            Survey.Survey.cssType = "bootstrap";
            var model = new Survey.Model(this.json);
            if (this.state.requestFailed) return <p>Failed!</p>
            if (!this.state.githubData) return <p>Loading...</p>
            return (
                <div className="App">
                    <div className="App-header">
                        <img src={logo} className="App-logo" alt="logo"/>
                        <h2>Welcome</h2>
                    <div className="side-by-side">
                        <div className="content-body">
                            {/*If you want to show survey, uncomment the line below*/}
                            <h1>Welcome:</h1>
                            <Survey.Survey
                                model={model}
                                onComplete={this.onComplete}
                                onValueChanged={this.onValueChanged(model)}
                        <StickyBox className="content-sidebar" offset={10}>
                            {<h5>Click here.</h5>}
                            {<p>{this.state.githubData.datastructure}</p>}
                        </StickyBox>
    export default App;
              

    It's not a React Issue. It's an issue in Survey.js-react.
    The cause of this is a combination of missuse of the componentWillReceiveProps event in reactSurvey.tsx in combination with the updateSurvey function in reactSurvey.tsx

    protected updateSurvey(newProps: any) {
        if (newProps) {
          if (newProps.model) {
            this.survey = newProps.model;
          } else {
            if (newProps.json) {
              this.survey = new ReactSurveyModel(newProps.json);
        } else {
          this.survey = new ReactSurveyModel();
        if (newProps) {
          for (var key in newProps) {
            if (key == "model" || key == "children") continue;
            if (key == "css") {
              this.survey.mergeCss(newProps.css, this.css);
              continue;
            if (
              key.indexOf("on") == 0 &&
              this.survey[key] &&
              this.survey[key].add
              let funcBody = newProps[key];
              let func = function(sender, options) {
                funcBody(sender, options);
              this.survey[key].add(func); //<= will re-add already subscribed listeners.... 
            } else {
              this.survey[key] = newProps[key];
    

    Instead of replacing all listeners on an Event on each updateSurvey-call they are added.
    Whenever the react event componentWillReceiveProps is triggered on the Survey Component it will add all by prop provided event listeners on top on the old list over the lifetime of the component. Basically the function bleeds old-state values into new-state values.

    @xadie yes you are right!
    @swilso793 We recommended to create model and add event listeners only once. For example:

      constructor(props) {
        super(props);
        var model = new Survey.Model(this.json);
        model.onComplete.add(this.onComplete);
        model.onValueChanged.add(this.onValueChanged);
        this.state = {
          surveyModel: model
      render() {
        return <Survey.Survey model={this.state.surveyModel} />;
    

    could you please try this approach?