How to fix 'Static HTML elements with event handlers require a role.'? - reactjs

My reactjs styledcomponent contains this code:
<a styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>
This works fine but the eslint is complaining:
Static HTML elements with event handlers require a role.
How can I fix this error?

you need to add a role props in your a tag to avoid this warning, for example a button
<a role = "button" styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>
I guess it is because the HREF props is missing in your anchor tag (not sure)

In my case, I used aria-hidden="true", then I was able to commit.
Before:
<i className="pwdicon" onClick={togglePasswordVisiblity} >
After I updated with aria-hidden:
<i className="pwdicon" onClick={togglePasswordVisiblity} aria-hidden="true" >
My problem was resolved.
Reference Link : https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md

The earlier answers do give specific examples, what I was missing is a list of roles.
If someone is looking for other roles, a partial list is listed here.
An example of a missing role is tab which I needed.
Edit: per the comment request, my personal error was solved by adding role, but I was missing a list of allowed roles, see above for a partial list and a more complete (or possibly complete) list here, thanks to the comment by Caiof.

You need to set the role explicitly. So, try the next code:
<a role="button" styling="link" onClick={this.gotoLink}>
<SomeComponent />
</a>
Also, as you can see I've modified the onClick handler by replacing arrow function on regular declaration. It would reduce annoying and expensive calculations.

just add aria-hidden to it
<a aria-hidden styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>

Just need to add the 'aria-hidden' attribute, like this:
<div onClick={handleClickCollectionCard} aria-hidden="true">

Related

href attribute is required in combination with history react module

I use the history React module to manage the session history, and have links such as:
<a
className="edit"
onClick={() => {
history.push(`/user/${this.props.match.params.id}/${i.slug}`);
}}
>
Edit User
</a>
This generates the following warning from ESLint:
The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-is-valid.md jsx-a11y/anchor-is-valid
Is there a way to resolve this warning without turning the hyperlink into a button?
(given the complexity of the CSS going on inside the repository, converting it to a button would be a lot of work.)
If I just add href, like below, then the ESLint warning is solved. But can the history module then still do its job properly?
<a
className="edit"
href={`/user/${this.props.match.params.id}/${i.slug}`} //extra line
onClick={() => {
history.push(`/user/${this.props.match.params.id}/${i.slug}`);
}}
>
Edit User
</a>
If using href is necessary you can do something like : href="javascript:void(0)"

React site warning: The href attribute requires a valid address. Provide a valid, navigable address as the href value jsx-a11y/anchor-is-valid

I am getting a warning on a React site I built
./src/components/layout/Navbar.js [1] Line 31: The href attribute requires a valid
address. Provide a valid, navigable address as the href value jsx-a11y/anchor-is-valid
on the following code:
<p>
{isEmpty(profile.website) ? null : (
<a
className="text-white p-2"
href={profile.website}
target="#"
>
<i className="fas fa-globe fa-2x" />
</a>
)}
{isEmpty(profile.social && profile.social.twitter) ? null : (
<a
className="text-white p-2"
href={profile.social.twitter}
target="#"
>
<i className="fab fa-twitter fa-2x" />
</a>
)}
{isEmpty(profile.social && profile.social.facebook) ? null : (
<a
className="text-white p-2"
href={profile.social.facebook}
target="#"
>
<i className="fab fa-facebook fa-2x" />
</a>
)}
</p>
Even though the warning appears only for the first link, the same warning occurs on the next link if I remove the first link temporarily or change the href of the first link to a static URL.
The links need to appear as just an icon.
I have tried things such as using a button (did not have the correct look), using a function to open the dynamic url, and trying to force the href to be a string by using '' + {profile.website}. Many other suggestions have not worked.
Is there a way to prevent the error, without changing the jsx-a11y rules? Is what I have done not a good pattern, or is it just a bug in React or JSX?
Use href="/#" to replace href="#" OR href="javascript:;" OR href="javascript:void(0);"
It should remove the warnings.
These worked for me to get rid off the warning;
...
<a href={() => false}>...</a>
I've used href="!#" to remove warnings.
This is just a warning not a error that href attribute requires a valid value as # points to nowhere you can add links to href attributes to remove this warnings or if you are still in early development phase just write
/* eslint-disable jsx-a11y/anchor-is-valid */
On top of your code it will remove the warnings from the terminal, the above line disables the rule for the specified file where it is written
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
const Header = () =>{
return(
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Navbar</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
</nav>
)
}
To also prevent default I use this:
<a href="/#" onClick={(e) => e.preventDefault()}>Link Text</a>
Insert space after # so no more warning about it
replace href="#" to href="# "
but better if use like that href="#something" => href="#profile"
please use <button> instead of <a> when there's no href attribute.
official reference
If you really have to use the a tag, it maybe help you:
<a href="#" onClick={ev => {ev.preventDefault(); onClick();}}>"Hello A Tag"</a>
try replacing
target="#"
to
target="_blank"
I got the similar warning for href, I did as follows. May be try this. I got rid of the warning and functionality is intact. I am not sure this is correct. But tried this.
let hrefLink = '#'; passed as a arg like href={hrefLink}
If you are trying to render a page link dynamically then you can switch out an <a> tag for a <div> tag instead. The warning message will go away.
// DON't DO THiS
<a className="page-link" href="javascript:void(0);" onClick={() => onPageChange(page)}>
{page}
</a>;
// TRY THIS INSTEAD
<div className="page-link" onClick={() => onPageChange(page)}>
{page}
</div>;
If you put "javascript" word in the href attribute then you will get a RED WARNING:
index.js:1375 Warning: A future version of React will block
javascript: URLs as a security precaution. Use event handlers instead
if you can.
Reference: EsLint error resolution page
I've used the href in tag a. it's remove warnings.
<a href>Pictures</a>
You also can hide this warning adding a eslint-disable-next-line comment:
// eslint-disable-next-line
<a
onClick={e => {
// do something
}}
>
example
</a>
I've used the following to remove warnings.
<a href="/">
If we have written correct url but it also gives the same error like I put www.reactjs.org then it also gives the same warning. To resolve these problem we have an attribute in anchor tag i.e.
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
className used for style.
href used for links.
target used for open a link into new tab or not.
Rel is used to outcome from that warning in react.
I don't see something wrong if I'm refering to this.
https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md
Check in these links. Some people had the same problem than you and it comes from a Link component. They fix it in adding an exception to .eslintrc:
first link => https://github.com/evcohen/eslint-plugin-jsx-a11y/issues/340
and the second link => How can I fix jsx-a11y/anchor-is-valid when using the Link component in React?
Let me know if it's helping.
Late to the game but surprised no one recommended window.location, which simply sets the same exact route as the current?
Other solutions such as "#", "/#", and "/" actually modify the current route right? For a more generic solution just use window.location to stay on the current page without modification.
<a href="window.location" onClick={...}> Better Solution </a>
If you really want your anchor tag to have an onClick method you must use a valid href link orelse it will throw an error , The href attribute requires a valid value to be accessible. If you cannot provide a valid href, but still need the element to resemble a link, use a button and change it with appropriate styles.
Change you button style with this property to make transparent
button{
background-color: Transparent;
background-repeat:no-repeat;
border: none;
cursor:pointer;
overflow: hidden;
outline:none;
}
and set the text inside the button to the resemble link color
I have use this color
.editcolor{
color: #1890ff;
}
I resolved my errors with this method.
I tried but most of the answers above did not work for me since the newer eslint does not allow most of them. Instead, it mentions disabling eslint for the specific line.
Simply add: // eslint-disable-next-line to the line which comes just before the jsx line that throws error.
Also, add this comment within {/* ... */} else it will show error.
Usage: {/* // eslint-disable-next-line */ }}
They advise the same thing:
Hope this solves it!
You just need to change "#" to "# ". Good luck
<li className="nav-item pointer">
<a onClick={logout} href="/#" className="nav-link">
LOGOUT
</a>
</li>
or just use
href="/"
Do Not Use: <a href='#'>Something</a> but instead use: <a href='/'>Something</a>

How to put an onClick event on an font awesome icon in react?

I am trying to set an onClick event on a fontawesome icon but it doesnt work when I do this.
<i class="fab fa-accessible-icon" onClick={this.removeItems}></i>
It only works when I put the onClick on p tags or h tags like this.
<h1 onClick={this.removeItems}><i class="fab fa-accessible-icon"></i></h1>
It is not possible to set event on icon itself? Doing this the second way is causing me style errors.
Edit: I did change the class to className, my bad. but its still not working and currently im bypassing it using around the icon and having the onClick on the span.
Here you can look into react docs which explains to use className instead of class.
Also wrap your <i> tag in button tag and use onClick() function there.
Well it should work like below...
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<i class="fa fa-cog" onClick="console.log('Clicked')"></i>
If its not try to wrap your icon into a button
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<button><i class="fa fa-cog" onClick="console.log('Clicked')"></i></button>
Perhaps try
<i className="fab fa-accessible-icon" onClick={this.removeItems}></i>
I was able to get
<i onClick={doSomething}>Testing</i>
to handle the click event, but it was rendered as jsx (ala render() method) -- assuming you are doing likewise.
You are confusing JSX with HTML. The i tag you have in your code is not plain html tag it is a javascript object(read more about jsx here). React takes care of binding the events for you, don't worry if you can't see onClick in your html.
Change class attribute to ClassName
<i className="fab fa-accessible-icon" onClick={this.removeItems}></i>
I think its work. check the demo https://stackblitz.com/edit/react-nh2bqu
If you're using react-fontawesome, you can use the FontAwesomeIcon component, and set both an id and an onClick:
<FontAwesomeIcon id={yourIdGoesHere} icon={faEdit} onClick={this.editItem} />
...
editItem = event => {
let idOfClickedIcon = event.currentTarget.id
...do something with the item associated with the id
}

jsx-a11y/no-static-element-interactions: how to make span clickable

In my project we have this lines of codes:
<span
onClick={this.toggleEditing}
>
{this.state.value}
</span>
Needless to say, it produces an error in eslint with message "Visible, non-interactive elements should not have mouse or keyboard event listeners jsx-a11y/no-static-element-interactions". But I don't know what is the best way to fix this situation, should we change it to button and change style to look like a span. I really don't have much experience with this problem.
Look at the documentation it beautifully tells you what to do.
https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md#how-do-i-resolve-this-error
For your case, the resolution is to add role="button"
<span onClick={this.toggleEditing} role="button">
{this.state.value}
</span>
I fixed it using this:
<span
role="button"
tabIndex={0}
title="Some title"
onClick={this.toggleEditing}
onKeyPress={this.toggleEditing}
>
{this.state.value}
</span>
What is the error? onClick translates to an event in the DOM which is valid (click on a span) so you should be able to make this work.

How to work around jsx-a11y/no-static-element-interactions restriction?

I used the following jsx to construct an entry in a FAQ table:
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
The idea is that when a user click on the entry, it will toggle the open state of the entry. In the other word, when a user clicks on an open FAQ entry, it will close it. Otherwise it will open it.
However the li tag triggers this eslint violation: Visible, non-interactive elements should not have mouse or keyboard event listeners jsx-a11y/no-static-element-interactions
Unfortunately I don't think there is alternative way to the above html markup.
Since it is jsx, it also does not allow override such as // eslint-disable-line jsx-a11y/no-static-element-interactions (The inline comment will be printed out to the web page)
So how I can work around it? Happy to use different jsx markup or jsx eslint override
For those who are looking for a workaround, use role="presentation" in your tag.
Here's how you could revise the markup to be semantically appropriate and get the onclick off the <li>
<li key={faqKey} className={styles.entry}>
<h3>
<button type='button' onClick={handleExpandFn}>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</button>
</h3>
<div className='add_a_panel_class_name_here'>
{faqEntry.answer}
</div>
</li>
So with the above:
the <h3> will make the titles of the FAQs easily searchable by screen reader users that are navigating by headings
placing the <button> inside of the <h3> gives you the appropriate element to attach a click event to (you want to use a button here because you're toggling state. an <a> should be used if you were going to a new page. You also don't need to add a tabindex to a button as they are inherently focusable).
There are some additional steps you'd likely want to implement, using ARIA expanded and controls attributes on the button, but the above should get you to a good base for moving beyond your error.
You could put eslint-disable-line in the jsx
<li // eslint-disable-line jsx-a11y/no-static-element-interactions
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
Another option, add role='presentation'
<li
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
role='presentation'
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
One solution I can remember is to use an anchor element with tab-index.
<a style={{display: 'list-item'}} tabIndex={-42} key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</a>
if you are trying to implement menu using li then the right solution is using role="menuitem" in your li tags.
More details about it: https://w3c.github.io/aria/#menuitem
To overcome or avoid this error in ES Lint.
You can use three things based on your needs and requirements
aria-hidden="true" - will remove the entire element from the accessibility API
role= "presentation" - The presentation role is used to remove semantic meaning from an element and any of its related child elements.
role= "none" - will remove the semantic meaning of an element while still exposing it to assistive technology.
There are limitations as well:
Hide content from assistive technology
Cannot be used on a focusable
Element cannot be used on the parent of an interactive element
You can actually add the eslint override as a comment in JSX.
You have to nest the comment inside of braces {}, so that it will be interpreted as JavaScript. Then, of course, since it is a JavaScript comment, it will not be rendered in the JSX.
Depending on your style preference, you can either do it on the line directly before the code
{/* eslint-disable-next-line */}
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
or, at the end of the same line
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}> {/* eslint-disable-line */}
Check out the docs for more information on using JavaScript inside of JSX.
use
aria-hidden="true"
on non interactive element tag. like
<span aria-hidden="true" onClick={() => void}>Text</span>
Instead of rolling my implementation of faq table with collapse/expand interactive feature, I replace it with react-collapsible.
It of course gets rid of the jsx-a11y/no-static-element-interactions as a result.

Resources