Why is onClick not shown in Element? - reactjs

This is my React code:
<button
className="show-all"
onClick={() => { console.log("button clicked");}}>
button
</button>
This is what rendered in the browser:
<button class="show-all">button</button>
I am so curious: Why is the onclick missing? This will not affect the function, but I just cannot see the onclick name.
The following code has the same problem.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
function shoot(){
console.log("shoot")
}
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
class ShowAlert extends Component {
showAlert() {
alert("I'm an alert");
}
render() {
return <button onClick={this.showAlert}>show alert</button>;
}
}
ReactDOM.render(
<>
<button onClick={() => console.log("good")}>
Click 1
</button>
<button onClick={shoot}>
Click 2
</button>
<button onClick={handleClick}>
Click 3
</button>
<ShowAlert />
</>
,
document.getElementById('root')
);
And I don't know if this small uncomfortable point is worth discussion.

React implements a synthetic events system that brings consistency and high performance to React apps and interfaces. It achieves consistency by normalizing events so that they have the same properties across different browsers and platforms.
A synthetic event is a cross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.
It achieves high performance by automatically using event delegation. In actuality, React doesn’t attach event handlers to the nodes themselves. Instead, a single event listener is attached to the root of the document. When an event is fired, React maps it to the appropriate component element.
Resource - https://blog.logrocket.com/a-guide-to-react-onclick-event-handlers-d411943b14dd/

As pointed out in the comments to the question and the previous answer, React does not render events in the DOM, so they are not shown in the HTML elements.
I would like to add that if you just want to inspect the React events you can use devtools for that.
For example, for Firefox, MDN provides nice instructions on how to inspect events in devtools, and here is an example for Chrome.

This feature is what I like most, unlike Angular. This is not just about listeners, but also props. React handles the DOM virtually, so everything works virtually than having them in real DOM.
I had the same question in previous days and I noted: why is it so? Just continue reading for what I found specific in React.
You might also surprise why className renders class in the HTML? I mean, you might confuse why class is shown, but not onclick?
In JavaScript, class conflicts with the keyword class and it has a different name, i.e., className. React JSX just works like JavaScript and it binding the class in HTML.
Similar to className, there is htmlFor to the for attribute. You can see for in the rendered HTML like you see class for className.
So, when a React element is rendered in the browser it will only show the HTML attributes, but not React props.
There is onclick in JavaScript and onClick is specific to React (however, React internally transforms it to onclick as pointed out in other answer - synthetic event) and thus onClick is not shown in the DOM when it renders. React updates and works in a virtual DOM.
The only thing you need to note that - do provided props match a DOM attribute case sensitively? If yes, it will show in rendered HTML. Otherwise, No.
I hope, you have now a better understanding about these.
If you would like to see attached listener and props, etc. then you can use React devtools.

Related

ReactDOM.render does not re-render the 2nd element on the list

im having problem with ReactJS, i
on index.js i have:
ReactDOM.render([<App />, <Footer />], document.getElementById('root'));
the problem is that Footer needs to add an 80px padding from the bottom only on certain pages
so on the render method i do
<div>
{isMobile && window.location.pathname.startsWith('/summary') &&
<div style={{height: 80}}></div> }
</div>
but it doesn't re-render when window.location.pathname changes,
i move around the web app and it doesn't change only when i hit F5 it renders correctly on that page.
i tried using events on window but they're aren't invoked as well...
window.addEventListener('locationchange', function(){
console.log('xxxxxxx location changed!');
})
window.addEventListener('hashchange', function(e){console.log('xxxxxx hash changed')});
window.addEventListener('popstate', function(e){console.log('xxxxxxx url changed')});
how i can make it re-render? or make Footer work as React component that can render ?
This is a common problem!
Out of the box, React is configured to operate on a single page (see Single Page Applications), which basically means it deletes what's shown on screen and renders new information when an update is required.
Naturally, simulating the routing behavior that's observable for non Single Page Apps is a little more difficult - check out React Router, which is a library created to tackle this exact issue.

Can we add events on react fragment?

In my case, I have to wrap up the content in the parent component without adding extra div element to the DOM. So, I wrapped the element with the react fragment. I got a use case to add the native browser event to the react fragment, Is that even possible?
Short answer, no, you can't add events on React Fragments. There is a detailed discussion over here, but as such, I don't think React Fragments will be supporting event handlers in the near future.
You may convert the your React Fragment (from <> </>) to a div element instead, and attach events to them.
return <div onClick={() => handleClick()}> </div>;
You can't add events on react fragment.
you can only add key only to react fragments like
<React.Fragment key={id}>
.....
</React.Fragment>
not with this
<key={id}>
.....
</>

Autofocus on reactstrap alerts using react functional component

I am using react hooks for my frontend designs and while creating a register form I have used various validations and I am depicting errors using reactstrap warning alerts.
And things are working fine but when focus is not implemented on these alers means when my page shows any of alert, it doesn't focus on that automatically.
I have tried basic codes for autofocus/ autoFocus or Focus() but nothing is working as per need.
My alert code look as shown below:
{
showAlreadyRegisteredAlert?
<Alert variant="warning" onClose={() => setShowAlreadyRegisteredAlert(false)} dismissible>
<p className="mb-0">
{content}
</p>
</Alert>
:null
}
I am just writing these alert codes in between my form inputs and whenever I need to call any of them I simply setValue for the commponent and alert box is called but still it lacks autofocus.
Any help will be appreciated. Thanks in advance!
I found the desired solution as I wanted my page should automatically focused on appearing alert boxes. I searched react-hooks official documention and get to know that we can use "useRef" for the purpose and below is my code for better understanding and clarification:
First: import useRef from react.
import React, {useState, useRef} from "react";
Second: create const with desired name using useRef as null.
const inputUser = useRef(null);
Third: set focus on your ref const after alert.
setShowAlreadyRegisteredAlert(true);
inputUser.current.focus();
Fourth: pass ref as const which you defined in step 2 inside your input field.
ref= {inputUser}

React Semantic-UI: Modal component with Form component? Is it possible?

So, I'm trying to use Semantic UI modal component with the form component.
My problem is that if I use these two together the UI becomes bad.
I created a sandbox about my current situation: https://codesandbox.io/s/2n1pj96ry
As you can see now the submit button does not attached to the form.
If I move the Form component directly inside the Modal component, like this:
<Modal...>
<Form>
...
</Form>
</Modal>
the submit will attached to the form, but the UI breakes down.
I tried to add different classes to these components (like ui modal to the Form component, but it doesnt worked well).
Do you have any suggetsion?
Thanks for you help!
You can use the as prop on the Modal to make it a form element.
<Modal
as={Form}
onSubmit={e => handleSubmit(e)}
open={true}
size="tiny">
Any button with the submit type in your modal will fire the onSubmit handler. I find this to be a nice way to opt-in to required fields and easy validation by the browser on form elements.
Be sure to pass the event to your submit handler and use the preventDefault method to avoid the browser from automatically trying to post your form.
Forked your sandbox and made a working example. The modal is changed to a <form> element, the Input has the required property and the browser will demand the element is valid before firing the onSubmit handler. The default form action is prevented, and you can handle as desired with whatever.

Testing for text contained in React component with Enzyme and Jest

For my React component I have the following:
const ArchiveButton = ({collection, onClick}) => {
return (
<span>
{ collection.archived &&
<Button bsStyle="link" onClick={onClick}><i className="fa fa-rotate-left" /> Unarchive</Button>
}
{ !collection.archived &&
<Button bsStyle="link" onClick={onClick}><i className="fa fa-archive" /> Archive</Button>
}
</span>
);
};
I'm attempting to test by passing in different values for collection.archived and I want to check for the existence of the text "Unarchive" vs "Archive". When I do a wrapper.find('Button') and try and check against .text() it is just <Button /> and the only way I've figured out how to test it is:
const wrapper = shallow(<ArchiveButton onClick={onClick} {...props}/>);
let button = wrapper.find('Button').prop('children');
expect(button[1]).toMatch(/\sUnarchive/);
Seems a bit off though, not sure. Thanks!
It's because you're using shallow rendering, so your nested Button component doesn't get rendered. As you've seen, you can access the nested component props to test the values you pass to it.
If you prefer to have the button content rendered, use normal rendering instead.
Note that the nested Button is not a normal DOM element, which would be rendered anyway even if you use shallow rendering, but it's instead a component itself.
If you think about it, if you don't use shallow rendering in your case, you're not really unit-testing your component, as you're also asserting something about the Button component. If you use shallow rendering and access the props of the nested component, you're really just testing that your code is calling the Button component with the correct arguments, and you're not making any assumptions as how the Button component will render.
This is normally what you want to do in a unit test.

Resources