Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

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

How to persist Step State on "Previous/Back" button click #63

Closed
gate3 opened this issue Aug 8, 2017 · 17 comments
Closed

How to persist Step State on "Previous/Back" button click #63

gate3 opened this issue Aug 8, 2017 · 17 comments

Comments

@gate3
Copy link

gate3 commented Aug 8, 2017

Hi, great library. This is my first time using this, i've tried to go through other issues but can't find what i need. The issue is that the data filled in, into a previous step goes missing as soon as i go to another step, i don't know if this is by design or an error, because wizard steps should normally retain state so users can go back. If this is by design, then i'd be really happy if i can get any suggestions on how to overcome this issue. Thanks.

@newbreedofgeek
Copy link
Owner

@gate3 this is by design. You make a valid point that a wizard should retain data going back too, but currently how it works is that clicking "next" calls a injected "isValidated()" method in that step and it's up to you on validating data and saving to state. The decision was made to keep it simple, as validation is involved and you need to prompt the user to fix data before saving to state, I only call isValidated() on "Next" where the user is committed to fixing issues and moving forward. Promoting users to fix issues on "back" is a broken UX - but I do see a use case for this.

At the moment clicking back does not trigger any local method so you can't save it to state unfortunately. You are welcome to make this an "option" and if your up for it you can raise a PR.

Here is the recommended way to make this an option:

  1. Create a new StepZilla option called "callValidatedOnBack", default this to false
  2. in StepZilla source, check where isValidated is called - I will have a check to only call this on "next" - if the user has set callValidatedOnBack to true then call it on back as well.
  3. if it's called on back, then pass in a prop to isValidated that indicates to the Step component that it was triggered by back and then you can decide on if you should trigger validation in your step or just save to state (if it's a back)

Hope that helps

@gate3
Copy link
Author

gate3 commented Aug 8, 2017

OK, seems like a good option. But I am thinking of saving to state using

componentWillUnmount

and then recovering from state in

componentWillMount

But for now, i want to attempt keeping state data in parent.

I'd like to know your thoughts about this please.

@gate3
Copy link
Author

gate3 commented Aug 9, 2017

Storing in parent state seems to work like a charm. What i'm doing is saving to parent state on using

componentWillUnmount

and then i passed in the particular state as props to each step. Then I'm setting the input text value as an uncontrolled input using

defaultValue

peek 2017-08-09 01-04

@newbreedofgeek
Copy link
Owner

@gate3 brilliant, of course. componentWillUnmount is the best way to do this as it puts the Step in full control and we dont need any core code changes to support this. Thanks for doing this. I will close this now.

@gate3
Copy link
Author

gate3 commented Aug 9, 2017 via email

@gate3
Copy link
Author

gate3 commented Aug 10, 2017 via email

@newbreedofgeek
Copy link
Owner

Good idea, but a PR is not needed. I will tag this Ticket "Useful Tips" and link it off the README/WIKI for others to see.

So please add your example to this ticket.

@gate3
Copy link
Author

gate3 commented Aug 10, 2017 via email

@newbreedofgeek newbreedofgeek changed the title Current Step State not being stored How to persist Step State on "Previous/Back" button click Aug 10, 2017
@newbreedofgeek
Copy link
Owner

@gate3
Copy link
Author

gate3 commented Aug 10, 2017

Say we have a parent component that uses stepzilla like this

const steps = [ {name:'Step1',component:<Step1 />} {...} ]

Create a state for the step in parent component

this.state = { step1:{someData:'',someData2:''} }

Create a function to collect data from the child component during 'componentWillUnmount'. Assign an id for each child so you can use a switch statement to know which child is passing the data, then overwrite the state in the parent

saveChildData (childId, dataObject){ switch (id){ case 1: this.setState({ step1:dataObject }) break; ... } }

Ensure you remember to break when using switch, i forgot to at first and it cost me some time before i could realize what was wrong.

Then modify the call to stepzilla component, passing the data from parent, id and the saveChildData function.

{name:'Step1',component:<Step1 id={1} storeFunc={this.saveChildData.bind(this) {...this.state.step1} />}

Then in the child component simply create a component to pass the data back to parent on componentWillUnload and also pass the data to your form components. You can't use a controlled input element bcos assigning props to it will mean you can't edit, so use an uncontrolled one.

<input defaultValue={this.props.someData} ref={(input) => this.someVal = input} />

Then the function to save the data goes like this

componentWillUnmount () { this.props.storeFunc({someData:this.someVal.value,... }

Thats it.

Note when trying to store data for an array of components, use the child state and restore the components using 'componentDidMount'

@newbreedofgeek
Copy link
Owner

@gate3 your contribution is very much appreciated!

@moisesnandres
Copy link

Hi @gate3 can you do an example on a gist? I tried to follow your steps but didn't work

@rickerd
Copy link

rickerd commented Dec 23, 2017

@gate3 is there an example somewhere? I can't get it to work and where to place the functions.

@vishagar81
Copy link

@newbreedofgeek I am just unable to get this working. Sadly, I do not get any errors too. I have followed your description but not sure whether I am missing something.

@sfblaauw
Copy link

sfblaauw commented Mar 1, 2019

Hi! I'm new using Reactjs but here is my gist for persisting data.
Please @newbreedofgeek and @gate3 let me know if I'm in the correct path.
Thanks for the module, it is awesome!

@mrkchang
Copy link

I don't think this works for going backwards

@packaging03
Copy link

This is excatly what I did that make it workfor normal text input field. However, it does not work on Input field.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants