React Router: How to Render Routes Without a Link Component
Tags: beginners, react, codenewbie
Published: 2021-02-23 21:09:16

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. 


![new recipe without using history](https://p69.f3.n0.cdn.getcloudapp.com/items/NQuJl48G/705581e1-f11e-44b0-8398-fbc01c15d938.gif?v=9be87249dc5036ea5ab0c8a2128cb016)


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. 


![AddRecipeCard component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/239atpm6888b1kyy67s3.png)

![clicking on card now leads to /NewRecipeForm route](https://p69.f3.n0.cdn.getcloudapp.com/items/kpu78ADk/293a3e0f-7fb4-4243-ba29-a17fe41bd1b9.gif?v=cf7ce29513dda0d98d5abe365462327d)


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.


![renderRecipes function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpn93l4h251b6f1qcalk.png)

![calling renderRecipes after editing a recipe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2n7l21or2mtmz1wdry2.png)

![example of rendering recipes on frontend](https://p69.f3.n0.cdn.getcloudapp.com/items/7Kup6WRo/38564141-548a-4d4b-9627-6c9e635f211f.gif?v=91eec852ebe4799034182c55190bdf23)


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. 


![history.push error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rveyxdrgvn6sksxhxwk.png)


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.


![importing BrowserRouter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wwq3bggyve10ql6m8wv.png)

![passing router props to RecipeContainer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5h5wglftukrwgqst6n9h.png)

![viewing history prop in RecipeContainer](https://p69.f3.n0.cdn.getcloudapp.com/items/yAu61RXW/12ffa779-aa31-4fb7-a0fe-cabafd06c0cf.gif?v=7c94b5c90d3506b00775600a78de0ff7)


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. 


![no history prop in RecipeComponent or RecipeModal](https://p69.f3.n0.cdn.getcloudapp.com/items/llu90b1P/d31d0e8e-56c7-4172-b87e-a5232a2ee1b7.gif?v=4bc925a0d4f8e2983188d6038bff1a05)


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.


![Passing history prop from RecipeContainer to RecipeComponent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns7fi86rei63v40fvs9a.png)
*Passing history prop from RecipeComponent to RecipeModal*


![Passing history prop from RecipeComponent to RecipeModal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjndr96c0iai09ymdoje.png)


![Using history.push in RecipeModal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwst54lpnpsqg1mioqpb.png)

![Rendering EditRecipeForm on frontend](https://p69.f3.n0.cdn.getcloudapp.com/items/ApuRXW0R/7215cd70-2747-4f81-92f9-afe4205e0180.gif?v=6b8699098876553ce17e64fafcc1508b)


Success! :)

Now I understand history in React Router just a little bit better and I hope anyone reading does too!