Font-awesome icon within button not activating onClick in React app - reactjs

I am happy I can use font-awesome in my projects. I want to put some bars as my open/close button for my menu. The icon itself is not clickable, but the small area between the icon and the border still activates the onClick. The console.log I put in my event handler shows that the icon does not pass the 'name' property needed to activate the state change. Does anyone know how to get around this?
I have tried wrapping it in span and i elements. The icon does show up, but is just not activating the onClick, probably because it is not passing the 'name' property.
My event handler:
menuClick(event) {
/*event.preventDefault();*/
const name = event.target.name;
console.log(name);
this.setState({[name]:!this.state[name]})
}
My button:
<button
name="menuOpen"
style={props.data.menuOpen ?
buttonStyle :
null}
onClick={props.menuClick}
className="menuOpenButton">
<FontAwesomeIcon name="menuOpen" icon="bars" size="3x" />
</button>
and the props are being passed to the child like this:
<Header
data={this.state}
menuClick={this.menuClick} />

Changing the event handler to look for the currentTarget fixed it.
const name = event.currentTarget.name

Related

React To Print not triggered when custom button is clicked

I have the following code to use React To print, a library to print a component:
<ReactToPrint
trigger={() =>
<SqIconButton action={(e)=>e} color={"success"}>
<AiIcons.AiFillPrinter style={{color: 'black',fontSize:'1rem'}}/>
</SqIconButton>
}
content={() => componentRef.current}
/>
And my custom Button SqIconButton reads as follows:
export default function SqIconButton({children,color="primary",fontColor="#000000",action,tip="",disableElevation=false,sxstyle={},classes}){
return(
<Tooltip title={tip}>
<Button
color={color}
variant="contained"
onClick={action}
disableRipple={disableElevation}
className={`TBButton ${classes}`}
sx={sxstyle}
>
{children}
</Button>
</Tooltip>
)
}
In the examples of React To Print code for its trigger nothing is referencing "onclick" property on buttons, examples mostly look like this: <button>print this</button> and if I use this element it actually works. But my custom button does not work as is, so I think I have to pass the onclick event over my action custom property, so I'm trying with action={(e)=>e}, but the button does nothing when I press it.
Documentation says about trigger:
A function that returns a React Component or Element. Note: under the hood, we inject a custom onClick prop into the returned Component/Element. As such, do not provide an onClick prop to the root node returned by trigger, as it will be overwritten
So I don't know if onclick will be overwritten how could I pass this event to a child button component.

Is there a way to reuse Bootstrap's OverlayTrigger component?

I have hundreds of objects rendered on the screen that are each wrapped in a <OverlayTrigger> (https://react-bootstrap.github.io/components/overlays/#overlaytrigger)
If these OverlayTriggers are displaying the same/similar text, is there a way I can just instantiate one and reuse that one, instead of rendering hundreds for each object that remain inactive until they're clicked/hovered over?
If you were able to use Overlay instead of OverlayTrigger you could do this by adding event handlers to the components that you want to trigger the overlay (e.g. onClick, onMouseOver/onMouseOut). The event handler would:
update the trigger to be the element that triggered the overlay (so the overlay is displayed alongside the element)
update the show state to ensure the overlay is displayed
The HTML would allow you to define a single Overlay element that can be used by multiple objects (in this case 4 buttons):
<div>
<Overlay target={target.current} show={show} placement="right">
<Tooltip id="button-tooltip">Simple tooltip</Tooltip>
</Overlay>
<Button onMouseOver={showOverlay} onMouseOut={showOverlay}>
Test
</Button>
<Button onMouseOver={showOverlay} onMouseOut={showOverlay}>
Test 2
</Button>
<Button onMouseOver={showOverlay} onMouseOut={showOverlay}>
Test 3
</Button>
<Button onMouseOver={showOverlay} onMouseOut={showOverlay}>
Test 4
</Button>
</div>
The show state and target ref would need to be introduced:
const [show, setShow] = useState(false); // Used to display the overlay
const target = useRef(null); // Used to store the reference to the HTML element that triggered the overlay
The showOverlay function would set the target ref to the HTML element that was clicked/hovered over, then set the flag to display the Overlay:
const showOverlay = (e) => {
target.current = e.target;
setShow(!show);
};
There's a working demo of this here.

React useRef to target specific div?

So I have this modal that is wrapped with an entire background div. My issue is that I added a close function on the background, so no matter where I click, it will close the modal.
I would like to have the useRef only target the background div and not work if I click any of the children inside of it
Here is the code
const modalRef = useRef();
const closeModal = e => {
if (modalRef.current.contains(e.target)) {
setShowModal(false);
}
}
return (
<>
{showModal ? (
<Background onClick={closeModal} ref={modalRef}>
<animated.div style={animation}>
<ModalWrapper showModal={showModal}>
<div>hi</div>
<CloseModalButton
aria-label='Close modal'
// onClick={() => setShowModal(!showModal)}
/>
</ModalWrapper>
</animated.div>
</Background>
) : null}
</>
);
};
So right now the ref is attached to the background, but if I console.log(modalRef.current) it will show me the entire jsx with all my children divs inside, but I only want to target the outside div aka the background
So whenever I click outside of my modal it will close
Note: when I console.log(modalRef.current) this is what shows up in the console aka my entire JSX
I'm also using styled-components, so I only want to target the top div which I called Background but shows sc-bdnylx iEsAwc so I have no idea how to target it since it doesn't have any ids or classNames
I tried to add this console.log(modalRef.current.children[0]) but when I implemented it into my function, it didn't work properly. This console.log does only show the divs below my Background div, but I haven't found anything about targeting just the Background only
You don't actually need to use refs here. Just add onClick={e => e.stopPropagation()} to one of the divs inside Background, like on ModalWrapper. It'll stop the click from passing through.

React Mapbox Extra Button Doesnt Work Inside Popup

I am working with mapbox react gl - It is working pretty nice so far... except one thing.
The user can add their hometown location to the map. When the hometown location appears, it can be clicked to view a popup. I want the user to be able to remove the location from the map from inside the popup - So I added a function that removes the location from the database when a button is clicked. The problem is when the button is inside the popup the function doesn't fire - and I have no idea why.
I have messed with the z index of the button but it seems like whenever the button is clicked, the onClose function is being called instead of my handleDeleteHome function...
Edit* If I remove the onClose function, the handleDeleteHome function fires.
Any help is appriciated! Thanks!
{selectedHome && (
<Popup
latitude={bandLocation[0]}
longitude={bandLocation[1]}
onClose={() => {setSelectedHome(null)}}
offsetLeft={23}
offsetTop={-10}
>
<div>
<h4>Home Town</h4>
<Button
onClick={(e) => {
e.preventDefault()
handleDeleteHome()
}}
color="danger">x</Button>
</div>
</Popup>
)}
Alright! Figured it out - If anyone else needs to know:
You need to add closeOnClick={false} to the popup!

Image flickering issue in React when image is conditionally rendered

I have a header and I want to show an image on its right when the mouse is over the header.
I am maintaining a variable editMode in the state which is set to true/false
Then I am conditionally rendering the image using onMouseOver and onMouse events.
Now when I hover over the header, the edit mode is set to true and the image shows up and when I move the cursor out of the header, the editMode sets to false and the image disappears.
I am maintaining a variable editMode in the state which is set to true/false consditionally rendering the image using onMouseOver and onMouse:
Problem: When I hover over the edit icon, it starts flicker.
class TempComponent extends React.Component {
constructor() {
super()
this.editModeToggler = this.editModeToggler.bind(this)
this.state = {
editMode: false
}
}
editModeToggler() {
console.log('called')
this.setState({editMode: !this.state.editMode})
}
render() {
return(
<div>
<h3
onMouseOut={this.editModeToggler}
onMouseOver={this.editModeToggler}
>
Title
</h3>
{this.state.editMode?
<img src='http://www.rebanet.it/images/banners/iscrizioni.png' />
:
null
}
</div>
)
}
}
You can find this code running over here: http://jsfiddle.net/Lu4w4v1c/2/
How do I stop this flickering. I have also tried using onMouseEnter and onMouseLeave as suggested here but it did not work. I dont know how but using these two events resulted in opposite of what I want. The first time the component loaded, everything was fine but as soon as I hover over the icon the whole dynamics changes. The icon shows up when the mouse is not over the header and it does not show up when the mouse is over the header. Please help
The code with onMouseEnter and onMouseLeave is over here: http://jsfiddle.net/Lu4w4v1c/3/
When you have the listener on h3, initially the image is not rendered so for the first time everything seems to be working fine, but once the image is rendered and you hover over the image it responds to the mouseout event of the heading and hides the image immediately which in turn triggers a mouseover on the h3 resulting in the flickering behaviour.
To solve your problem you can simply attach the listener on the container. Updated your fiddle http://jsfiddle.net/Lu4w4v1c/4/ with
<div onMouseOut={this.editModeToggler}
onMouseOver={this.editModeToggler}>
<h3>
Title
</h3>
{this.state.editMode?
<img src='http://www.rebanet.it/images/banners/iscrizioni.png' />
:
null
}
</div>
If you have a container that is going to do onmouseover event that renders a div inside you should use onMouseLeave. The example fiddles has onmouseleave too.
https://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_event_mouseleave_mouseout
this shows the problem

Resources