Aria In Jsx
title: "ARIA Attributes in JSX" weight: 13 description: "Learn how to apply ARIA attributes conditionally in JSX, manage dynamic ARIA states with React state, use aria-expanded, aria-selected, and aria-current, and avoid common ARIA-in-React pitfalls." date: 2026-06-28 lastmod: 2026-06-28 tags: [accessibility, react]
ARIA attributes in JSX should be applied conditionally based on component state, using React state variables to control attributes like aria-expanded (open/closed), aria-selected (selected/unselected), and aria-current (current page), with proper re-rendering on state changes.
## What You'll Learn
You will apply ARIA attributes in JSX, manage dynamic ARIA values with React state, use conditional rendering for ARIA, and avoid common mistakes like mixing ARIA with semantic HTML.
## Why It Matters
ARIA attributes must reflect the current state of the component. An accordion section that is expanded should have aria-expanded=true. If the state changes, the ARIA attribute must update. React's state management makes this natural.
## Real-World Use
A React accordion component uses state.isOpen to control aria-expanded on the button. When the user clicks, isOpen toggles, React re-renders, and the button's aria-expanded updates automatically. Screen reader users hear the correct state.
## ARIA State Management
```mermaid
flowchart TD
A[Component State] --> B[ARIA Attribute]
B --> C[Screen Reader]
C --> D{Renders correctly?}
D -->|Yes| E[Accessible]
D -->|No| F[Update ARIA binding]
F --> A
Conditional ARIA in JSX
Use state to control ARIA attributes and spread syntax for cleaner code.
function Accordion({ title, children }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-controls="accordion-content"
>
{title}
<span aria-hidden={true}>{isOpen ? '-' : '+'}</span>
</button>
<div
id="accordion-content"
role="region"
hidden={!isOpen}
>
{children}
</div>
</div>
);
}
// Tab component with ARIA state management
function TabPanel({ tabs, activeTab, onTabChange }) {
return (
<div>
<div role="tablist" aria-label="Content tabs">
{tabs.map((tab, index) => (
<button
key={index}
role="tab"
aria-selected={activeTab === index}
aria-controls={`panel-${index}`}
onClick={() => onTabChange(index)}
>
{tab.label}
</button>
))}
</div>
{tabs.map((tab, index) => (
<div
key={index}
id={`panel-${index}`}
role="tabpanel"
hidden={activeTab !== index}
>
{tab.content}
</div>
))}
</div>
);
}
// Navigation with aria-current
function Nav({ currentPage }) {
const pages = ['Home', 'Products', 'About'];
return (
<nav aria-label="Main">
<ul>
{pages.map(page => (
<li key={page}>
<a
href={`/${page.toLowerCase()}`}
aria-current={currentPage === page ? 'page' : undefined}
>
{page}
</a>
</li>
))}
</ul>
</nav>
);
}
Common Mistakes
- Hard-coding ARIA attributes instead of making them conditional
- Forgetting to update ARIA attributes when state changes
- Applying ARIA roles to semantic HTML elements that already have them
- Using aria-selected incorrectly on non-selectable elements
- Mixing ARIA with incorrect state values
- Not using aria-controls to associate controls with their targets
- Setting aria-hidden on focusable elements
Practice and Challenge
Practice 1: Add aria-expanded to a collapsible component. Practice 2: Create a tab panel with proper aria-selected and aria-controls. Practice 3: Add aria-current to navigation links. Practice 4: Fix an accordion that hard-codes aria-expanded. Practice 5: Create a live region that announces state changes.
Challenge: Build an accessible dropdown menu component with multiple ARIA attributes: aria-expanded on the trigger, role="listbox" on the menu, aria-activedescendant for keyboard navigation, and aria-selected on menu items. Use React state to manage all ARIA values dynamically.
FAQ
Mini Project
Create a React ARIA pattern library with three components that use conditional ARIA: Accordion (aria-expanded), Tab Panel (aria-selected, aria-controls, role="tablist"), and Menu Button (aria-expanded, aria-haspopup, role="menu"). Each component should pass axe-core testing.
What's Next
Focus Management with Hooks covers using useRef and useEffect for focus management.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro