After updating to React 16.9.0 I'm getting big warnings like this:
Warning: A future version of React will block javascript: URLs as a security precaution. Use event handlers instead if you can. If you need to generate unsafe HTML try using dangerouslySetInnerHTML instead. React was passed "javascript:;".
It comes from code like this:
const Component = ({someAction}) => (
<a href="javascript:void(0)" onClick={someAction}>click me</a>
);
Looking at the StackOverflow question about which “href” value should I use for JavaScript links in HTML it seems most of you agree javascript:void(0)
is the best option, which will be no longer possible in React 16.9.0.
Just replacing with href="#"
is problematic, since the browser will scroll to the top of the page and change the displayed URL. Especially if you use hash-links for routing this is very problematic.
I could update my whole codebase to have e.preventDefault();
in each and every event handler, but this seems hard to do, especially when the event handlers are automatically created from Redux action creators or hooks. I do not look for the answer "just include e.preventDefault();
" everywhere!
Also using a <button>
means I have to deal with lots of unwanted styles applied.
So I was wondering: Are there any solutions specific to the library React to get a working <a>
link that just triggers an action without side effects? I want to change the code as little as possible and get rid of deprecation warnings.
Another alternative to JavaScript void 0 is to use return false. When the click returns false, the browser will not take any action.
Refs are a function provided by React to access the DOM element and the React element that you might have created on your own. They are used in cases where we want to change the value of a child component, without making use of props and all.
To cause anchors to do nothing on click in React, we can call e. preventDefault in the click handler function of the anchor.
In React blog post:
URLs starting with
javascript:
are a dangerous attack surface because it’s easy to accidentally include unsanitized output in a tag like<a href>
and create a security hole.In React 16.9, this pattern continues to work, but it will log a warning. If you use
javascript:
URLs for logic, try to use React event handlers instead.
I personally prefer to use it like this:
<a href="#!" onClick={clickAction}>Link</a>
I came up with a component like this:
import React, {useCallback} from 'react';
function AHrefJavascript({ children, onClick, ...props }) {
const handleClick = useCallback(
e => {
e.preventDefault();
return onClick(e);
},
[onClick]
);
return (
<a href="#javascript" {...props} onClick={handleClick}>
{children}
</a>
);
}
It will just wrap the event handler to create a new one that also calls e.preventDefault()
. It will add a hash link to href
which does not trigger the deprecation warning. Using the power of hooks it only changes the event handler, when the passed in handler is updated. One problem with this that in the browser you can still open this link in a new tab, so it is not quite as good as a link with a javascript:void(0)
, which would prevent that.
It is easy to use, the component looks like this:
const Component = ({someAction}) => (
<AHrefJavascript onClick={someAction}>click me</a>
);
So probably one could replace a href="javascript:void(0)"
with AHrefJavascript
across the project and then just add an import for the component everywhere.
In the end maybe the best option is to use a <button>
and go through the hoops to remove all the unwanted styles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With