How to toggle text without jquery in react? - reactjs

I'm trying to make a menu in react, that turns into a dropdown menu on smaller devices. I want to avoid using jQuery, since as far as I know you should avoid using it in React.
I want the dropdown menu to, well, drop down only if you click a certain thing on the navbar, to reduce the place it would take on the website if it would be always opened on smaller devices. In my case now, the stuff I click is "dropdown. My dropdown menu works, but I want to make my "V" into a "O" when the menu expands, and back to "V" when I close the menu.
I tried to do it with If, but I couldn't figure it out.
JSX:
<div id="container">
<h1 id="logo">Logo</h1>
<h1 id="navitem1">Menu option1</h1>
<h1 id="navitem2">Menu option2</h1>
<h1 id="navitem3">Menu option3</h1>
<h1 id="dropdown" onClick={DropDown}>V</h1>
</div>
const DropDown = () => {
if (document.getElementById('dropdown').innerText = 'V'){
document.getElementById('dropdown').innerText = 'O'
}
}
The If method I'm using here changes the "dropdown" element to O, but I don't know how to change it back to V.

in react you don't manipulate dom directly.
you can handle it with useState hook. first define the state in the component.
const [dropDownText,setDropDownText] = useState("V")
so your DropDown function should be :
const DropDown = () => {
if (dropDownText=== 'V'){
setDropDownText("O")
}else{
setDropDownText("V")
}
}
and the the element should be
<div id="container">
<h1 id="logo">Logo</h1>
<h1 id="navitem1">Menu option1</h1>
<h1 id="navitem2">Menu option2</h1>
<h1 id="navitem3">Menu option3</h1>
<h1 id="dropdown" onClick={DropDown}>{dropDownText}</h1>
</div>

Related

How to use isAccessibilityElement && accessibilityElementsHidden in ReactJS class to solve Voiceover issue

I have a Vertical menu that is styled as a dropdown.
on iPhone, when Voiceover is on, double tab will open the dropdown, swipe Right will go through menu items, and when gets to the last menu item, Swipe Right will close the dropdown and gives focus to the first link outside of Menu.
Now, dropdown menu is closed. and menu items are not visible. Normally, one single Left swipe should moves the focus from outside link to the dropdown header while Voiceover is ON.
but the problem is, it takes multiple Left Swipe equal to the number of menu items 4+ 1 to get from outside link to dropdown header. Voiceover is not announcing anything, I can only see on iPhone screen Voiceover text reading Manu item which is the same as <a role="menuitem">.
it looks like Voiceover still recognizes the menu items although the dropdown menu is closed.
If I do NOT open dropdown menu, 1 right swipe moves focus from dropdown header to outside link, and then 1 left swipe move focus from outside link to dropdown header. the problem happens when I open dropdown menu and swipe right through menu items.
I tried to resolve this by giving UL, Li , <a> the combination of these attributes but did not work.
When menu is closed:
aria-hidden=true, tabIndex=-1, display=none, visibility=hidden
but did not work.
I am wondering if I can implement isAccessibilityElement && accessibilityElementsHidden for React JS.
I see how the import command and code for React Native but nothing for React JS.
My Question is: when dropdown menu is closed, lets say focus is on outsideLink, how can I bring focus to dropdownHeader with one Left Swipe ?
How to force Voiceover to ignore menu items when dropdown menu is closed.
Note: my module is a Class in React JS.
Really appreciate any help.
import React, { Component } from 'react'
// help needed : how to import UISwipeGestureRecognizer for React JS
class App extends Component {
constructor(props){
super(props)
this.state = {
menuOpen: false,
}
this.closeMenu = this.closeMenu.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
this.handleSwipe = this.handleSwipe.bind(this);
}
componentDidMount () {
window.addEventListener('touchstart', handleSwipe);
}
closeMenu(event){
this.setState({menuOpen: false});
this.handleSwipe(event);
}
toggleMenu(event){
this.setState({menuOpen: !this.state.menuOpen});
}
handleSwipe(event){
const outsideLinkFocused = event.target.classList.contains('outsideLink');
const itemsArray = [...document.getElementsByClassName('item')];
if(outsideLinkFocused){
itemsArray.map(item => {
// need Help here
item.isAccessibilityElement = false;
item.accessibilityElementsHidden = true;
});
}
}
render() {
return (
<div className="Container">
<div className="NavContainer">
<button className="dropdownHeader">
Dropdown Header
</button>
<ul className="menu" role="menu">
<li className="item" role="none">
<a role=="menuitem" href="#"> item 1</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 2</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 3</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 4</a>
</li>
</ul>
</div>
<div className="ArticleContainer">
<a className="outsideLink" href="#"> Outside Link </a>
</div>
</div>
)
}
}
This module is more complex and all the handlers work fine. I just wrote a short version here.

How to use UISwipeGestureRecognizer in ReactJS

I have a Vertical menu that is styled as a dropdown.
on iPhone, when Voiceover is on, double tab will open the dropdown, swipe Right will go through menu items, and when gets to the last menu item, Swipe Right will close the dropdown and gives focus to the first link outside of Menu.
Now, dropdown menu is closed. and menu items are not visible. Normally, one single Left swipe should moves the focus from outside link to the dropdown header while Voiceover is ON.
but the problem is, it takes multiple Left Swipe equal to the number of menu items 4+ 1 to get from outside link to dropdown header. Voiceover is not announcing anything, I can only see on iPhone screen Voiceover text reading Manu item which is the same as <a role="menuitem">.
it looks like Voiceover still recognizes the menu items although the dropdown menu is closed.
If I do NOT open dropdown menu, 1 right swipe moves focus from dropdown header to outside link, and then 1 left swipe move focus from outside link to dropdown header. the problem happens when I open dropdown menu and swipe right through menu items.
I tried to resolve this by giving UL, Li , <a> the combination of these attributes but did not work.
When menu is closed:
aria-hidden=true, tabIndex=-1, display=none, visibility=hidden
but did not work.
I am wondering if I can implement UISwipeGestureRecognizer for React JS.
I see how the import command and code for React Native but nothing for React JS.
My Question is: when dropdown menu is closed, lets say focus is on outsideLink, how can I bring focus to dropdownHeader with one Left Swipe ?
How to force Voiceover to ignore menu items when dropdown menu is closed.
Note: my module is a Class in React JS.
Really appreciate any help.
import React, { Component } from 'react'
// help needed : how to import UISwipeGestureRecognizer for React JS
class App extends Component {
constructor(props){
super(props)
this.state = {
menuOpen: false,
}
this.closeMenu = this.closeMenu.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
this.handleSwipe = this.handleSwipe.bind(this);
}
componentDidMount () {
window.addEventListener('touchstart', handleSwipe);
}
closeMenu(event){
this.setState({menuOpen: false});
this.handleSwipe(event);
}
toggleMenu(event){
this.setState({menuOpen: !this.state.menuOpen});
}
handleSwipe(event){
const outsideLinkFocused = event.target.classList.contains('outsideLink');
const dropdownHeader = document.getElementsByClassName('dropdownHeader')[0];
const leftSwipe = UISwipeGestureRecognizer.direction == 'left'; // I need help with leftSwipe condition
if(outsideLinkFocused && leftSwipe){
dropdownHeader.focus();
}
}
render() {
return (
<div className="Container">
<div className="NavContainer">
<button className="dropdownHeader">
Dropdown Header
</button>
<ul className="menu" role="menu">
<li className="item" role="none">
<a role=="menuitem" href="#"> item 1</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 2</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 3</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 4</a>
</li>
</ul>
</div>
<div className="ArticleContainer">
<a className="outsideLink" href="#"> Outside Link </a>
</div>
</div>
)
}
}
This module is more complex and all the handlers work fine. I just wrote a short version here.

Hamburger menu from HTML to ReactJS

I'm trying to "converting" my code from HTML to ReactJS. What I tried and I couldn't make it worked is this line of code:
<div className = "title-bar" data-responsive-toggle = "center_menu">
<button className = "menu-icon" type = "button" data-toggle></button>
<div className = "title-bar-title"></div>
</div>
When I'm pressing that hamburger icon, that list "Home, Extensii etc" should appear. In HTML I made it worked fine. ReactJS it's not taking my data-responsive-toggle center_menu id. How should look the code, what is the correct syntax?
P.S.: I'm new in React, I'm trying to learn it.
well I don't know about whether you want it to look normal all the way and just have that burger on smaller screens or it's a burger menu all along but generally speaking for what you have asked, you need conditional classes to actually toggle between display:block; and display:none; and you need to handle that with the click event, so basically:
<div className ="title-bar">
<button className = "menu-icon" type = "button" onClick={this.toggleMenu}></button>
<div className = "title-bar-title"></div>
</div>
<div className={`example-menu ${this.isclicked}?" collapsed-menu": " closed-menu" `}>
<ul class = "menu dropdown" data-dropdown-menu>
<li>Home
....
<li>Contact</li>
</ul>
</div>
and that's what this.toggleMenu does:
toggleMenu() {
this.setState(state => ({
isclicked: !state.isclicked
}));
}
needless to talk about those two classes collapsed-menu and closed-menu, they would be sth like these:
.collapsed-menu{
....
display:block;
}
.closed-menu{
...
display:none;
}
There are several tutorials available on how to do it, e.g. here: https://css-tricks.com/hamburger-menu-with-a-side-of-react-hooks-and-styled-components/
Also you could use npm libraries to achieve the expected results.
what about the css (media query), did you specify the min-width value for the display??

Is there a way to create a react popup modal without using a third party package

I tried using the technique below, but the modal does not blur out the rest of the content. At the same time, I would like to make it reusable and avoid manipulating the elements' z-index
return (
<>
<div className='dashboard-main-neworder' onClick={newOrder}>
<img alt='New Order' src={addorder}></img>
<span>New Order</span>
</div>
{selected && (
<div className='neworder'>
<div className='neworder-title'>
<p>ORDER DETAILS</p>
</div>
You may want to check out portals (https://reactjs.org/docs/portals.html).
They provide a way to attach react nodes somewhere else in the dom tree (let's say next to you #app node so that your modal is always on top of your application, and you can then add a blur effect if that's what you want on your app below the modal.

React - render after single item modification in array

My problem goes like this:
I'm rendering an array of items using "map".
Each rendered item also includes a toggle button component that i created. You can refer this as regular checkbox.
The checkbox value will decided if the rendered item will have a specific css class, with transitions.
Here come's the problem.
On state change, i update the whole list. Therefore, the whole list is being re-rendered. Therefore, i get the relevant item with the relevant boolean value. Despite that, this item isn't modified, it's re-rendered, so the css doesn't change from A to B, it's just getting a new css class instead the previous, so the TRANSITION DOESN'T WORK.
The rendered array:
{this.state.extensions.map((curr,index)=>{
return <div className="single-extension" key={'extension-' + Utils.guid()}>
<div className="toggle-area">
<ToggleButton onChange={(value)=>{
this.handleAssociateExtension(index,value);
}} active={curr.associated}/>
</div>
<div className={ClassNames({'details':true, 'on': curr.associated})}>
<div className="link-text">{curr.link_text}</div>
<div className="description">{curr.description}</div>
<div className="landing-page">{curr.landing_page}</div>
</div>
</div>
})}
The update function:
handleAssociateExtension(index, value) {
let extensions = Utils.cloneObject(this.state.extensions);
if (extensions[index]) {
extensions[index].associated = value;
}
this.setState({extensions: extensions});
}
Thank you in advance! :)

Resources