While creating my most recent project, I came across a situation in how I wanted to use React Router. React Router provides the options to easily create links that link to a specific component and also render a URL defined by the coder. However, what if you don't always want to use links? My partner and I thought it would be cool to have a card in our RecipeContainer that, when clicked, would take a user to the NewRecipeForm.
So how to get our component to link to our NewRecipeForm route?
After some time of research, I found out that we could use an object called 'history' to render our specific route upon a certain action (i.e. clicking on a card component). There were two different ways to do this, depending on if our component was a function or a class. I had built this particular component as a function, and so I implemented a hook called 'useHistory'. This hook allowed me to push a URL into the history object, so that upon a certain action, I would be taken to that URL.
Voila! It worked! Surprisingly easily. Now we can do the same thing in a class component. Let's say that I want the recipes page to render once my EditRecipeForm (a class component) is submitted. I can create a function called 'renderRecipes' which uses
history.push to render the recipes URL. I can then call this function after my form has been submitted.
Great! Using history works in a class component too! However, I ran into some trouble when I tried the same thing in our RecipeModal, which was also a class component.
Each RecipeModal had an edit button and a delete button. I wanted the edit button to link to a route for the EditRecipeForm, but I kept getting the error, "Cannot read property 'push' of undefined". Basically saying, there is no history object. But why?
The solution was surprisingly and frustratingly simple.
BrowserRouter has its own history object, so any component rendered within this router has access to that history object as long as we pass it down as props. This was the case for our RecipeContainer, as you can see when we view props for RecipeContainer using Dev Tools.
However, if we look at our props for our RecipeComponent and RecipeModal, we can see that there is no history object. It didn't get passed down from the RecipeContainer to the RecipeModal.
I didn't figure this out in time before our project was due, so I just ended up changing our RecipeModal from a class component to a functional component and using the 'useHistory' hook again; however, if I had passed down that history object to the RecipeModal, my previous attempt would've worked just fine.
Now I understand history in React Router just a little bit better and I hope anyone reading does too!