2

I am making a resume builder application and the whole structure was almost done.

Complete working codesandbox:

Edit next-dynamic-testing-issue (forked)

Here I have made components into stepper for each section,

index.js

<form onSubmit={handleSubmit}>
        <Stepper
          steps={sections}
          activeStep={currentPage}
          activeColor="red"
          defaultBarColor="red"
          completeColor="green"
          completeBarColor="green"
        />

        {currentPage === 1 && (
          <>
            <BasicDetails />
            <button onClick={next}>Next</button>
          </>
        )}

        {currentPage === 2 && (
          <>
            <EmploymentDetails />
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <button onClick={prev}>Back</button>
              <button onClick={next}>Next</button>
            </div>
          </>
        )}

        {currentPage === 3 && (
          <>
            <pre>{JSON.stringify(value, null, 2)}</pre>
            <div style={{ display: 'flex', justifyContent: 'space-between' }}>
              <button onClick={prev}>Back</button>
              <button onClick={handleSubmit}>Submit</button>
            </div>
          </>
        )}
      </form>

Steps to reproduce issue:

-> In Step 1 Enter First Name, Last Name, and Profile Summary

-> Click on Next button to move to next step.

-> Then click the back button to move backward to Step 1 (Currently in Step 2)

-> Here the values in First Name, Last Name are there but the value entered in text editor alone gets lost

Please refer the below image with text editor value entered for better understanding of the problem I am facing..

Text editor value alone gets lost if we switch forth/back the steps. But the entered value is stored in the form Context and not rendered in the Text Editor box.

enter image description here

Note:

Text editor is made as a component and it was used in Step 1 (For profile summary) and also in Step 2 (For employment description) and in both cases switching between steps, the value entered inside the text editor gets lost.

Analysis:

Based on my understanding, this happens because on navigating to other steps, the component get re-rendered and the EditorContainer component gets called and in text_editor.js it was given

this.state = {
  editorState: EditorState.createEmpty(),
};

So it was created as empty.

So how can I control the component from getting re-rendered so that the data entered in text editor won't get lost.

Kindly please help me to retain the values entered inside the text editor. Big thanks in advance..

Undefined
  • 851
  • 5
  • 20
  • 48

3 Answers3

2

This happens because we're only saving our EditorContainer value to our Context, but we're not using it when we rerender the EditorContainer component.


The fix would be to pass the saved value as prop to our EditorContainer component.

Then before we render the EditorContainer, we'll convert that value to EditorState which can be done using convertFromHTML function, and set that as our editorState state.

Step 1: Pass value prop to EditorContainer

// basic_details.js
<EditorContainer
 name="profileSummary"
  value={basicDetails.profileSummary}
  onChange={(event) => handleInputChange(event)}
/>

// employment_details.js
<EditorContainer
  name="description"
  value={inputField.description}
  onChange={(event) => handleInputChange(index, event)}
/>

Step 2: Convert the value prop to EditorState

// text_editor.js
...

componentDidMount() {
  // https://draftjs.org/docs/api-reference-data-conversion/#convertfromhtml

  const { value } = this.props;
  const blocksFromHTML = convertFromHTML(value);
  const state = ContentState.createFromBlockArray(
    blocksFromHTML.contentBlocks,
    blocksFromHTML.entityMap,
  );

  const editorState = EditorState.createWithContent(state);
  this.setState({ editorState });
}

That's it! Check the demo below.

Edit Fix demo to check value if is string.

Edit next-dynamic-testing-issue (forked)

bertdida
  • 4,988
  • 2
  • 16
  • 22
1

This is a great question. This is basically a design approach issue: For a scenario like yours, you need to design your component this way: enter image description here

let's analyze the picture:

MAIN COMPONENT:

This is the component that should hold the state for the entire form-filling process. STE1-4 Are just views that allows you to input data that must all be updated in the main component. So This means, you must have state in main component and pass the state properties and props, including their update/setter methods.

STEP COMPONENT This applies for all Step Components. These components should do nothing except display the form step using state values received via props and update state by using setter methods, which are also received via props.


Conclusion:

Put your state in your main component, each step component should only display the form and update the main state. This means that by the time each step component is re-rendered, it will receive values updated in the main component. And you will achieve that via props.

Mosia Thabo
  • 4,009
  • 1
  • 14
  • 24
  • Thanks for your explanation in detail.. Could you kindly please provide the solution by forking the above given codesandbox in question.. I am new in react js and javascript and hence seeking a example way of solution.. Kindly provide working codesandbox as a solution and thanks once again.. – Undefined Sep 03 '20 at 14:48
  • Okay, I'll fork your CodesAndBox now quickly. – Mosia Thabo Sep 03 '20 at 14:50
  • Sorry for the late response. I just forked your code and tested it. It seems to be working fine. After filling in values, and then click next... and then back, those values are still there because I can see you used Context. Which is another approach. – Mosia Thabo Sep 03 '20 at 15:25
  • No try once again.. I have explained in question clearly that first name and last name value is there if we are coming back but the text editor value alone gets lost.. There are totally 3 fields in the ```Step 1``` .. Please fill all the 3 fields (including text editor ) and click ```Next``` button then you will be redirected to ```Step 2``` then click ```Back``` button, now in ```Step 1``` only first two input fields value is there but the 3rd input which is a text editor value gets lost and it is empty.. But in form context the value is there whereas in UI , that value not get binded.. – Undefined Sep 03 '20 at 15:36
  • In form JSON, the entered value was there but if we switch between the steps then already entered text editor (Profile Summary) value not got binded.. – Undefined Sep 03 '20 at 15:41
  • Hope you understand the problem clearly.. The above given codesandbox really has a problem in binding of value to the text editor while switching between the steps.. Kindly please go through once again and provide working solution please.. – Undefined Sep 03 '20 at 15:43
  • I have also attached image to my question for explaining better about the problem I am facing.. Kindly please help.. – Undefined Sep 03 '20 at 15:51
  • Oh Ok. I see what you mean. Let me check again. – Mosia Thabo Sep 03 '20 at 15:58
0

It's very simple - you need to store editors state in your parent component. Try to use BasicDetails state for this.