React Developer Interview Prep
Core React Concepts
The Building Blocks of React
React applications are built from reusable pieces of code called components. Think of them like Lego bricks. You build small, self-contained bricks (a button, a user profile picture) and then assemble them into larger, more complex structures (a navigation bar, a full user profile page).
Modern React focuses on functional components. These are just JavaScript functions that return what looks like HTML. This HTML-like syntax is called JSX, and it's what allows you to describe your user interface right inside your JavaScript code.
function WelcomeMessage() {
return <h1>Hello, world!</h1>;
}
This WelcomeMessage component is a simple function that returns a heading. To use it, you'd render it in your application like an HTML tag: <WelcomeMessage />.
JSX isn't exactly HTML. There are a few key differences. For instance, since class is a reserved word in JavaScript, you use className for CSS classes. You can also embed any valid JavaScript expression directly inside your JSX using curly braces {}.
A button with dynamic text:
<button>Sign up as {user.name}</button>
Making Components Dynamic
Static components aren't very useful. We need ways to get data into them and to manage data that changes over time. React gives us two primary tools for this: props and state.
Props (short for properties) are for passing data from a parent component down to a child component. This flow is one-way, which makes the logic easier to follow. A parent component holds the data and passes it to its children, who then display it.
// Parent Component
function UserProfile() {
const userData = { name: 'Alex', avatarUrl: 'path/to/image.png' };
return <Avatar user={userData} />;
}
// Child Component
function Avatar(props) {
return <img src={props.user.avatarUrl} alt={props.user.name} />;
}
In the example above, UserProfile passes a user object as a prop to the Avatar component. Avatar then accesses this data via its props argument.
What about data that changes based on user interaction, like a form input or a button click? That's where state comes in. State is data managed inside a component. When state changes, React automatically re-renders the component to reflect the new data.
To manage state in functional components, we use hooks. The most common one is the useState hook().
import { useState } from 'react';
function Counter() {
// `count` is the state variable.
// `setCount` is the function to update it.
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
</div>
);
}
Calling useState(0) does two things: it creates a piece of state named count initialized to 0, and it gives us a function, setCount, to update that state later. You never modify state directly (e.g., count = 1). You always use the setter function.
Responding to Users
Now let's combine state with event handling. To make our counter work, we need to update the state when a user clicks a button. In React, event handlers are named using camelCase, like onClick or onMouseOver.
We pass a function to the event handler. When the event occurs, React calls our function.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
Every time the button is clicked, the handleClick function is called, which in turn calls setCount. This tells React that the state has changed, triggering a re-render of the Counter component with the new count value.
Conditional Logic and Lists
Often, you'll need to show different things based on the state or props. This is called conditional rendering. You can use standard JavaScript logic like if statements or the ternary operator to decide what to render.
A common pattern is to show a loading message while data is being fetched, and the content once it arrives.
function UserGreeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <p>Welcome back!</p>;
}
return <p>Please sign in.</p>;
}
// Or using a ternary operator inside JSX
function UserGreetingTernary({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? <p>Welcome back!</p> : <p>Please sign in.</p>}
</div>
);
}
Finally, to render a list of items, you'll typically use the Array.prototype.map() method. You take an array of data and map it to an array of React elements.
When you do this, React needs a way to keep track of each element in the list. You must provide a unique key prop for each item in the list. This helps React identify which items have changed, are added, or are removed, making updates much more efficient. The key should be a stable, unique string or number from your data, like an item's ID.
function TodoList({ todos }) {
const listItems = todos.map(todo =>
<li key={todo.id}>
{todo.text}
</li>
);
return <ul>{listItems}</ul>;
}
Now that you have a handle on the core concepts, it's time to test your knowledge.
What are the fundamental, reusable building blocks of a React application's UI?
In JSX, how would you correctly assign the CSS class 'container' to a div element?
These building blocks—components, props, state, events, and list rendering—are the foundation of almost every React application you'll encounter.