question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature Request: Allow injecting a custom component for NavLink to render to enhance support for HOCs

See original GitHub issue

Background: I’m using Radium to style my React components. Radium works by wrapping the target component’s render function, searching for style props on DOM-node children and replacing them according to the current UI state (hovering/focusing/…). However, Radium does not do this for non-DOM-node children, since it does not know what the component is actually doing with the style prop. This is the case for React Router’s Link and NavLink components

Usually, this is solved by wrapping the React component using Radium’s HOC, as you can do with Link like in this snippet, which renders a Link with a red background, switching to green once you hover over it:

import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Link} from "react-router-dom";
import Radium from "radium";

const RadiatingLink = Radium(Link);

const App = () =>
  <BrowserRouter>
    <RadiatingLink
      to="/test3"
      style={{ background: "red", ":hover": { background: "green" } }}
    >
      LinkTest
    </RadiatingLink>
  </BrowserRouter>

render(<App />, document.getElementById("root"));

But, if we were to replace Link with NavLink in this example it wouldn’t work, because NavLink internally renders a Link not wrapped by the Radium HOC.

To solve this problem, I propose to add a new “renderComponent” prop to NavLink, which defaults to Link and gets rendered instead of a hardcoded Link component. This allows users to wrap the Link component rendered by NavLink (Or even render something completely different).

If this were implemented, it would allow injecting a custom render component like this:

import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Link, NavLink} from "react-router-dom";
import Radium from "radium";

const RadiatingLink = Radium(Link);

const App = () =>
  <BrowserRouter>
    <NavLink
      to="/test3"
      renderComponent={RadiatingLink}
      style={{ background: "red", ":hover": { background: "green" } }}
    >
      LinkTest
    </NavLink>
  </BrowserRouter>

render(<App />, document.getElementById("root"));

This would also fix https://github.com/FormidableLabs/radium/issues/907

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
jakubrpawlowskicommented, Feb 10, 2018

I also don’t like that NavLink can’t be wrapped in HOC.

For temporary solution I nested all NavLinks inside divs and styled background of those divs on hover with Radium. Maybe it helps somebody.

import React from 'react'
import Radium from 'radium'
import {NavLink} from 'react-router-dom'

const navigation = () => {
    const navStyle = {
        display: "grid",
        gridTemplateColumns: "repeat(4, 1fr)",
        lineHeight: "64px",
        textAlign: "center",
        borderBottom: "1px solid #ddd"
    }
    const makeHoverable = {
        display: "grid",
        ":hover": {
            backgroundColor: "#f7f7f7"
        }
    }
    const aStyle = {
        textDecoration: "none",
        fontWeight: "bold",
        color: "#666"
    }
    const aActiveStyle = {
        color: "#444",
        borderBottom: "3px solid orange"
    }
    return (
        <nav style={navStyle}>
            <div style={makeHoverable} key="homeHoverable"><NavLink style={aStyle} exact activeStyle={aActiveStyle} to="/">Home</NavLink></div>
            <div style={makeHoverable} key="clientHoverable"><NavLink style={aStyle} exact activeStyle={aActiveStyle} to="/client">Client</NavLink></div>
            <div style={makeHoverable} key="serverHoverable"><NavLink style={aStyle} exact activeStyle={aActiveStyle} to="/server">Server</NavLink></div>
            <div style={makeHoverable} key="contactHoverable"><NavLink style={aStyle} exact activeStyle={aActiveStyle} to="/contact">Contact</NavLink></div>
        </nav>
    )
}

export default Radium(navigation)
0reactions
ackvfcommented, Mar 27, 2018

You can walk around this with a Route. It’s even documented in the React Router Training.

You can pass what to render as a render prop (below) or you can write it directly within the BetterNavLink as in the linked example. (above)

const BetterNavLink = ({ children, ...linkProps }) => (
  <Route
    path={linkProps.to}
    exact={linkProps.exact}
    children={ ({ match }) => children({active: !!match, linkProps}) } 
  />
)

Then in the render of your NavBar

<BetterNavLink exact to="/pdp">
  {
    ({active, linkProps}) => (
      <div className={`list-group-item list-group-item-dark ${active ? 'active' : ''}`}>
        <Link {...linkProps}>
          <span className="label">PDP</span>
        </Link>
      </div>
    )
  }
</BetterNavLink>

result is

<div class="list-group-item list-group-item-dark active">
  <a href="/pdp">
    <span class="label">PDP</span>
  </a>
</div>
Read more comments on GitHub >

github_iconTop Results From Across the Web

Allow injecting a custom component for NavLink to render to ...
To solve this problem, I propose to add a new "renderComponent" prop to NavLink , which defaults to Link and gets rendered instead...
Read more >
Hide current component before rendering ... - Stack Overflow
I am building a single page web app based on react routing where I want to Hide current component before rendering the next...
Read more >
React Higher-Order Components in TypeScript - Medium
Higher-order components (HOCs) in React are a powerful tool for code reuse between ... Enhancers: Wrap a component with additional functionality/props.
Read more >
React Router Tutorial – How to Render, Redirect, Switch, Link ...
Let's start by creating the navigation bar for our app. This component will make use of the <NavLink /> component from react-router-dom ....
Read more >
How to handle navigation in your app with React Router Link
In this article, we'll explore the navigation possibilities in a React app and we'll take a look at the React Router Link component....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found