Using a nested NavLink to conditionally render JSX
Kevin Sassé
Posted on October 28, 2022
I've been learning React.js for the past three weeks at Flatiron School and have spent this entire week working on my end-of-phase project. One of the core requirements for the project is that it uses React Router.
Our single-page application displays a list of all the currently active NFL quarterbacks, as of 10/24/2022. The user can click on the player cards show/hide a player's stats as well as edit the stats and add players to a favorite list. We also included the ability to sort by different stats and a search feature.
One of the issues we encountered was how to only show the Search and Sort features on specific endpoints. Initially we tried to set state equal to the endpoint of the link that was clicked and use a ternary to determine which JSX elements should be returned.
return (
<>
<nav className="link-container">
<NavLink className="linkButtons" to="/" onClick={handleLinkClick}>Home</NavLink>
<NavLink className="linkButtons" to="/form" onClick={handleLinkClick}>New Player Form</NavLink>
<NavLink className="linkButtons" to="/favorites" onClick={handleLinkClick}>Favorites List</NavLink>
<NavLink className="linkButtons" to="/activelist" onClick={handleLinkClick}>Active List</NavLink>
</nav>
{pathName === "/form" || pathName === "/player/:id/EditForm" ?
null
:
<div className="search-sort">
<Search changeSearch ={changeSearch}
changeSearchValue = {changeSearchValue}
searchValue = {searchValue} />
<Sort changeSortBy = {changeSortBy}/>
</div>
}
</>
)
}
This had limited success and worked on the form to add a new player but not the one to edit a player.
The console showed the correct path names for most of the endpoints. If state was being updated correctly, the final "/" should have been "/player/:id/EditForm". The link is still routing to the edit player form but appears as the home endpoint in state. We believe the cause of this issue was that the link to the edit form is nested within the player card component itself instead of the Header component like the new player form.
We tried a few different ways to try and force the correct endpoint into state by passing callback functions through the various components, and did successfully get state to display the correct endpoint. Unfortunately this had issues with the ternary as the ":id" value wasn't getting passed into the Header component. This was overly complex and would only get more involved to get the ternary working properly.
Sometimes you need to take a step back, and rethink your approach to a problem. We were able to solve this issue by using the onClick
event to set state to either "true" or "false" based on the name of the <NavLink>
.
const handleLinkClick =(e) => {
e.preventDefault()
const { name, pathname } = e.target
if(name === "home" || name === "Favorite Players" || name === "Active Players") {
setDisplayStatus(true)
} else {
setDisplayStatus(false)
}
changePageUrl(pathname)
}
We also had to pass the handleLinkClick
function as a prop to the player card component to make it available to the edit form link on each card. We then were able to refactor our ternary to render the Search and Sort elements based on the state value.
return (
<>
<nav className="link-container">
<NavLink className="linkButtons" name="home" to="/" onClick={handleLinkClick}>Home</NavLink>
<NavLink className="linkButtons" name="New Player Form" to="/form" onClick={handleLinkClick}>New Player Form</NavLink>
<NavLink className="linkButtons" name="Favorite Players" to="/favorites" onClick={handleLinkClick}>Favorite Players</NavLink>
<NavLink className="linkButtons" name="Active Players" to="/activelist" onClick={handleLinkClick}>Active Players</NavLink>
</nav>
{displayStatus === false ?
null
:
<div className="search-sort">
<Search changeSearch ={changeSearch}
changeSearchValue = {changeSearchValue}
searchValue = {searchValue} />
<Sort changeSortBy = {changeSortBy}/>
</div>
}
</>
)
}
If one of the falsey endpoints is clicked, the <Search/>
and <Sort/>
components will not be displayed. This approach is much simpler than trying to conditionally render components using a nested endpoint.
Posted on October 28, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.