React Events, Forms, and DOM Interview Questions
Table of Contents + β
This page follows the way event and DOM questions usually unfold in interviews. It starts with Reactβs event model, moves into conditional UI and forms, and then covers DOM attributes, styling, lists, refs, and browser-facing behavior.
This page includes 23 questions in this topic group.
Event system basics
What is the difference between HTML and React event handling?
Below are some of the main differences between HTML and React event handling,
-
In HTML, the event name usually represents in lowercase as a convention:
<button onclick="activateLasers()"></button>Whereas in React it follows camelCase convention:
<button onClick={activateLasers}> -
In HTML, you can return
falseto prevent default behavior:<ahref="#"onclick='console.log("The link was clicked."); return false;'/>Whereas in React you must call
preventDefault()explicitly:function handleClick(event) {event.preventDefault();console.log("The link was clicked.");} -
In HTML, you need to invoke the function by appending
()Whereas in react you should not append()with the function name. (refer βactivateLasersβ function in the first point for example)
What are synthetic events in React?
SyntheticEvent is a cross-browser wrapper around the browserβs native event. Its API is same as the browserβs native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers. The native events can be accessed directly from synthetic events using nativeEvent attribute.
Letβs take an example of BookStore title search component with the ability to get all native event properties
function BookStore() { function handleTitleChange(e) { console.log("The new title is:", e.target.value); console.log('Synthetic event:', e); // React SyntheticEvent console.log('Native event:', e.nativeEvent); // Browser native event e.stopPropagation(); e.preventDefault(); }
return <input name="title" onChange={handleTitleChange} />;}List of common synthetic events are:
onClickonChangeonSubmitonKeyDown,onKeyUponFocus,onBluronMouseEnter,onMouseLeaveonTouchStart,onTouchEnd
Conditional UI and form handling
What are inline conditional expressions?
You can use either if statements or ternary expressions which are available in JS(and JSX in React) to conditionally execute or render expressions. Apart from these approaches, you can also embed any expressions in JSX by wrapping them in curly braces and then followed by JS logical operator &&. It is helpful to render elements conditionally within a single line and commonly used for concise logic, especially in JSX rendering.
<h1>Hello!</h1>;{ messages.length > 0 && !isLogin ? ( <h2>You have {messages.length} unread messages.</h2> ) : ( <h2>You don't have unread messages.</h2> );}What are controlled components?
A controlled component is a React component that fully manages the form elementβs state(e.g, elements like <input>, <textarea>, or <select>)) using Reactβs internal state mechanism. i.e, The component does not manage its own internal state - instead, React acts as the single source of truth for form data.
The controlled components will be implemented using the below steps,
- Initialize the state using
useStatehooks in function components or inside constructor for class components. - Set the value of the form element to the respective state variable.
- Create an event handler(
onChange) to handle the user input changes throughuseStateβs updater function orsetStatefrom class component. - Attach the above event handler to form elementβs change or click events
Note: React re-renders the component every time the input value changes.
For example, the name input field updates the username using handleChange event handler as below,
import React, { useState } from "react";
function UserProfile() { const [username, setUsername] = useState("");
const handleChange = (e) => { setUsername(e.target.value); };
return ( <form> <label> Name: <input type="text" value={username} onChange={handleChange} /> </label> </form> );}In these components, DOM does not hold the actual data instead React does.
Benefits:
- Easy to implement validation, conditional formatting, or live feedback.
- Full control over form data.
- Easier to test and debug because the data is centralized in the componentβs state.
What are uncontrolled components?
The Uncontrolled components are form elements (like <input>, <textarea>, or <select>) that manage their own state internally via the DOM, rather than through React state.
You can query the DOM using a ref to find its current value when you need it. This is a bit more like traditional HTML.
The uncontrolled components will be implemented using the below steps,
- Create a ref using
useRefreact hook in function component orReact.createRef()in class based component. - Attach this
refto the form element. - The form element value can be accessed directly through
refin event handlers orcomponentDidMountfor class components
In the below UserProfile component, the username input is accessed using ref.
import React, { useRef } from "react";
function UserProfile() { const usernameRef = useRef(null);
const handleSubmit = (event) => { event.preventDefault(); console.log("The submitted username is: " + usernameRef.current.value); };
return ( <form onSubmit={handleSubmit}> <label> Username: <input type="text" ref={usernameRef} /> </label> <button type="submit">Submit</button> </form> );}Note: Here, DOM is in charge of the value. React only accesses the value when needed (via ref).
Benefits:
- Less boilerplate - no need for
useStateandonChange. - Useful for quick form setups or when integrating with non-React code.
- Slightly better performance in very large forms (fewer re-renders).
In most cases, itβs recommend to use controlled components to implement forms. In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself.
Class-based version
class UserProfile extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.input = React.createRef(); }
handleSubmit(event) { alert("A name was submitted: " + this.input.current.value); event.preventDefault(); }
render() { return ( <form onSubmit={this.handleSubmit}> <label> {"Name:"} <input type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> ); }}DOM attributes and styling
Why React uses className over class attribute?
React uses className instead of class because of a JavaScript naming conflict with the class keyword.
-
classis a reserved keyword in JavaScript In JavaScript, class is used to define ES6 classes:class Person {constructor(name) {this.name = name;}}If you try to use class as a variable or property name, it will throw a syntax error. Since JSX is just JavaScript with XML-like syntax, using class directly in JSX would break the parser.
-
JSX Is JavaScript
When you write JSX like this:
<div class="btn">Click</div>It will be compiled to:
React.createElement('div', { class: 'btn' }, 'Click');But
classis invalid in this object literal context (since it clashes with the JS keyword), hence React instead uses className.<div className="btn">Click</div>which compiles to:
React.createElement('div', { className: 'btn' }, 'Click');React then translates
classNametoclassin the final HTML DOM. -
Aligns with DOM APIs In vanilla JavaScript, you interact with element classes using:
element.className = 'my-class';React follows this convention, staying consistent with the DOM APIβs property name rather than HTMLβs attribute.
How do you use styles in React?
The style attribute accepts a JavaScript object with camelCased properties rather than a CSS string. This is consistent with the DOM style JavaScript property, is more efficient, and prevents XSS security holes.
const divStyle = { color: "blue", backgroundImage: "url(" + imgUrl + ")",};
function HelloWorldComponent() { return <div style={divStyle}>Hello World!</div>;}Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes in JavaScript (e.g. node.style.backgroundImage).
How events are different in React?
Handling events in React elements has some syntactic differences:
- React event handlers are named using camelCase, rather than lowercase.
- With JSX you pass a function as the event handler, rather than a string.
Lists and UI rendering behavior
What is the impact of indexes as keys?
Keys should be stable, predictable, and unique so that React can keep track of elements.
In the below code snippet each elementβs key will be based on ordering, rather than tied to the data that is being represented. This limits the optimizations that React can do and creates confusing bugs in the application.
{ todos.map((todo, index) => <Todo {...todo} key={index} />);}If you use element data for unique key, assuming todo.id is unique to this list and stable, React would be able to reorder elements without needing to reevaluate them as much.
{ todos.map((todo) => <Todo {...todo} key={todo.id} />);}Note: If you donβt specify key prop at all, React will use index as a keyβs value while iterating over an array of data.
What are the Pointer Events supported in React?
Pointer Events provide a unified way of handling all input events. In the old days we had a mouse and respective event listeners to handle them but nowadays we have many devices which donβt correlate to having a mouse, like phones with touch surface or pens. We need to remember that these events will only work in browsers that support the Pointer Events specification.
The following event types are now available in React DOM:
onPointerDownonPointerMoveonPointerUponPointerCancelonGotPointerCaptureonLostPointerCaptureonPointerEnteronPointerLeaveonPointerOveronPointerOut
How do you loop inside JSX?
You can simply use Array.prototype.map with ES6 arrow function syntax.
For example, the items array of objects is mapped into an array of components:
<tbody> {items.map((item) => ( <SomeComponent key={item.id} name={item.name} /> ))}</tbody>But you canβt iterate using for loop:
<tbody> for (let i = 0; i < items.length; i++) { <SomeComponent key={items[i].id} name={items[i].name} /> }</tbody>This is because JSX tags are transpiled into function calls, and you canβt use statements inside expressions. This may change thanks to do expressions which are stage 1 proposal.
How do you conditionally apply class attributes?
You shouldnβt use curly braces inside quotes because it is going to be evaluated as a string.
<div className="btn-panel {this.props.visible ? 'show' : 'hidden'}">Instead you need to move curly braces outside (donβt forget to include spaces between class names):
<div className={'btn-panel ' + (this.props.visible ? 'show' : 'hidden')}>Template strings will also work:
<div className={`btn-panel ${this.props.visible ? 'show' : 'hidden'}`}>How do you use React label element?
If you try to render a <label> element bound to a text input using the standard for attribute, then it produces HTML missing that attribute and prints a warning to the console.
<label for={'user'}>{'User'}</label><input type={'text'} id={'user'} />Since for is a reserved keyword in JavaScript, use htmlFor instead.
<label htmlFor={'user'}>{'User'}</label><input type={'text'} id={'user'} />How do you combine multiple inline style objects?
You can use spread operator in regular React:
<button style={{ ...styles.panel.button, ...styles.panel.submitButton }}> {"Submit"}</button>If youβre using React Native then you can use the array notation:
<button style={[styles.panel.button, styles.panel.submitButton]}> {"Submit"}</button>Refs and browser-facing behavior
How do you re-render the view when the browser is resized?
You can use the useState hook to manage the width and height state variables, and the useEffect hook to add and remove the resize event listener. The [] dependency array passed to useEffect ensures that the effect only runs once (on mount) and not on every re-render.
import React, { useState, useEffect } from "react";function WindowDimensions() { const [dimensions, setDimensions] = useState({ width: window.innerWidth, height: window.innerHeight, });
useEffect(() => { function handleResize() { setDimensions({ width: window.innerWidth, height: window.innerHeight, }); } window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []);
return ( <span> {dimensions.width} x {dimensions.height} </span> );}Using Class Component
You can listen to the resize event in componentDidMount() and then update the dimensions (width and height). You should remove the listener in componentWillUnmount() method.
class WindowDimensions extends React.Component { constructor(props) { super(props); this.updateDimensions = this.updateDimensions.bind(this); }
componentWillMount() { this.updateDimensions(); }
componentDidMount() { window.addEventListener("resize", this.updateDimensions); }
componentWillUnmount() { window.removeEventListener("resize", this.updateDimensions); }
updateDimensions() { this.setState({ width: window.innerWidth, height: window.innerHeight, }); }
render() { return ( <span> {this.state.width} x {this.state.height} </span> ); }}How do you pretty print JSON with React?
We can use the <pre> tag so that the formatting of the JSON.stringify() is retained:
const data = { name: "John", age: 42 };
function User { return <pre>{JSON.stringify(data, null, 2)}</pre>;}
const container = createRoot(document.getElementById("container"));
container.render(<User />);Class-based version
const data = { name: "John", age: 42 };
class User extends React.Component { render() { return <pre>{JSON.stringify(data, null, 2)}</pre>; }}
React.render(<User />, document.getElementById("container"));How do you focus an input element on page load?
You need to use useEffect hook to set focus on input field during page load time for functional component.
import React, { useEffect, useRef } from "react";
const App = () => { const inputElRef = useRef(null);
useEffect(() => { inputElRef.current.focus(); }, []);
return ( <div> <input defaultValue={"Won't focus"} /> <input ref={inputElRef} defaultValue={"Will focus"} /> </div> );};
ReactDOM.render(<App />, document.getElementById("app"));Class-based version
You can do it by creating ref for input element and using it in componentDidMount():
class App extends React.Component { componentDidMount() { this.nameInput.focus(); }
render() { return ( <div> <input defaultValue={"Won't focus"} /> <input ref={(input) => (this.nameInput = input)} defaultValue={"Will focus"} /> </div> ); }}
ReactDOM.render(<App />, document.getElementById("app"));How can we find the version of React at runtime in the browser?
You can use React.version to get the version.
const REACT_VERSION = React.version;
ReactDOM.render( <div>{`React version: ${REACT_VERSION}`}</div>, document.getElementById("app"));How do you add Google Analytics for React Router?
Add a listener on the history object to record each page view:
history.listen(function (location) { window.ga("set", "page", location.pathname + location.search); window.ga("send", "pageview", location.pathname + location.search);});How do you apply vendor prefixes to inline styles in React?
React does not apply vendor prefixes automatically. You need to add vendor prefixes manually.
<div style={{ transform: "rotate(90deg)", WebkitTransform: "rotate(90deg)", // note the capital 'W' here msTransform: "rotate(90deg)", // 'ms' is the only lowercase vendor prefix }}/>How do you pass an event handler to a component?
You can pass event handlers and other functions as props to child components. The functions can be passed to child component as below,
function Button({ onClick }) { return <button onClick={onClick}>Download</button>;}
export default function downloadExcel() { function handleClick() { alert("Downloaded"); }
return <Button onClick={handleClick}></Button>;}How do you prevent a function from being called multiple times?
If you use an event handler such as onClick or onScroll and want to prevent the callback from being fired too quickly, then you can limit the rate at which callback is executed. This can be achieved in the below possible ways,
- Throttling: Changes based on a time based frequency. For example, it can be used using _.throttle lodash function
- Debouncing: Publish changes after a period of inactivity. For example, it can be used using _.debounce lodash function
- RequestAnimationFrame throttling: Changes based on requestAnimationFrame. For example, it can be used using raf-schd lodash function
How do you set default value for uncontrolled component?
In React, the value attribute on form elements will override the value in the DOM. With an uncontrolled component, you might want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value.
render() { return ( <form onSubmit={this.handleSubmit}> <label> User Name: <input defaultValue="John" type="text" ref={this.input} /> </label> <input type="submit" value="Submit" /> </form> );}The same applies for select and textArea inputs. But you need to use defaultChecked for checkbox and radio inputs.