And we're going to use this set of supplies in order to do it. We have our React context to use a reducer hook from React, route components from React Router, and a custom hook to pull it all together.
So we'll start with our React context to collect all the information we need to share between the high-level wizard and the individual steps. In our wizard component, we're going to iterate over the children in order to grab ones that match our step component that we'll build out, and look for the name prop and collect our list of names as our steps. We're going to set the default step as the first one in that list, and then declare our reducer.
The wizard reducer we'll look at next, but we're setting the initial state to the current step as the first step in the flow. The initial values to help seed any initial data that we're gathering in the flow, and that list of steps as well. And the value return by user reducer will be set as the wizard context provider. We're going to display all the children passed through our wizard component, and then initial redirect from the index of this feature to the default step. So anything directing or linking into this feature does not have to know what the first step is.
Now our wizard reducer is fairly simple as reducers go. We have two actions which contains the sync to update our current step, and then update values in which to, as the name suggests, update the values we're gathering throughout the lifetime of our wizard. And here's the step component we were referencing before. So we have our component prop and our name, and then we're going to pull in our use wizard context hook, we'll declare next in order to spread this state as props on our components. This is similar to other APIs that ReactRouter used to use in the past, and we're going to map the name of our step as the path of our route. And we'll see how useful having the state map to props on our component can be next.
In our wizard context hook, we're going to again, pull in that context using the use context hook from React. And as the result of useReducer, we're going to get the wizard state and that dispatch function in order to send actions to our reducer. We're going to wrap these dispatch actions into our own custom functions just to make it easier for anything consuming this hook to call them. So we have our sync action, our updateValues action, and then we have something called goToStep, which will use both of those in order to either call updateValues if we have them, and then call sync, and then push forward in history, or just push and navigate to the next step or previous step depending on how it's used. And so our next step will look for making sure that we're not on the last step in our in the wizard, and then call goToStep if we're not. versus the previous step, which will make sure we're not on the first step and allow us to call previous, if that's the case, and then we'll return it all as a result of our hook.
And so here's that API again, let's take a look at how an individual step can compose this. As we declared as part of one of our directives, that can be form agnostic. And so we have goToNextStep, goToPreviousStep, and wizard.state all coming from that hook the step component itself. But again, we could use that hook if we wanted to directly. This cleans up a little bit of boilerplate and having to always pull in that hook and allows for a bit of a dependency injection in case you want to test this individually later. And so our handleSubmit function just uses a regular form. And we're going to grab all the form values from the HTML form using the new form date API and this object from entries method, and then call goToNextStep with that object to values. We can even use existing values from wizard state in order to set the default on our input, and then very familiar looking actions, such as our previous button and submit in order to either go backwards or forwards.
Comments