surveyjs / survey-library

Free JavaScript form builder library with integration for React, Angular, Vue, jQuery, and Knockout.
https://surveyjs.io/form-library
MIT License
4.18k stars 808 forks source link

setState in onComplete will disrupt complete function #3205

Open Louis-He opened 3 years ago

Louis-He commented 3 years ago

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

Reporting a bug

What is the current behavior?

Can't setState in onComplete function. Unexpected behaviour will occur. Specifically, surveyjs will take the user back to the first page of the survey.

What is the expected behavior?

No matter if setState in onComplete function or not, surveyjs should always show "completedHtml" after users complete their survey

How would you reproduce the current behavior (if this is a bug)?

Create a survey, add 'setState' in the onComplete function. Surveyjs will take the user back to the firstpage when it should display completedHtml

Provide the test code and the tested page URL (if applicable)

Tested page URL:

The whole project is here: https://github.com/UTACE/ACEKnow/commit/88cfe54f3248625ff619809889f334e5da5df79a. You can compile the react project and visit this page: http://localhost:3000/tocanada. After you complete the survey, you will be guided to complete the survey again which is not expected.

Test code

If the example is too complicated, here is some related code:

class CanadaPage extends React.Component {
  constructor(props){
    super(props);

   this.onComplete = this.onComplete.bind(this)
  }

  ...
  json = {
    title: "...",
    startSurveyText: "...",
    firstPageIsStarted: true,
    pages: [...],
    completedHtml: "..."
  };

  onComplete(survey, options) {
    console.log('Updating State');
    console.log("Result JSON:\n" + JSON.stringify(survey.data, null, 5));

    console.log(this)
    //  this.setState({
    //    result: survey.data
    //  })
    // When we add setState code commented out above, the survey will not work as intended
  }

Specify your

andrewtelnov commented 3 years ago

@Louis-He What you are trying to achieve? setState will re-render your Component and since I do not see your code, I have no idea what is wrong and what you expect. I guess, your Component is a wrapper for SurveyJS react component.

Thank you, Andrew

Louis-He commented 3 years ago

Yes, and somewhat re-render the component will interfere with survey.js. If SurveyJS react component gets re-rendered, will it start back from the start?

danteese commented 2 years ago

Did you find a workaround?

frimmy commented 1 year ago

@danteese did you find a work around 😅 cc: @Louis-He

bitrecipe commented 1 year ago

I had a similar situation. I resolve this issue by just wrapping Survey component with React.memo

const _SurveyComp = ({ setState }) => {
  const survey = new Model(surveyJson);
  survey.focusFirstQuestionAutomatic = false;

  const alertResults = useCallback((sender) => {
    const results = JSON.stringify(sender.data);
    setState(1);
  }, []);

  survey.onComplete.add(alertResults);

  return <Survey model={survey} />;
}

const SurveyComp = React.memo(_SurveyComp);

function App() {

  const [state, setState] = useState(0);

  return <>
    {state}
    <SurveyComp setState={setState} />
  </>;
}