Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Atlassian hiring for React JS roles
Atlassian builds team collaboration and software development tools such as Jira, Confluence, Trello, Bitbucket and Jira Service Management. It runs a significant engineering team in Bengaluru and follows a distributed work policy. Hiring in India covers software engineers, quality and reliability engineers, data engineers and data scientists who work on product analytics and platform features.
For React JS roles, this Atlassian practice set focuses most on React Hooks (6), Props and State (5), React Fundamentals (5), State Management (5). It has 24 medium, 6 hard questions, so you can start easy and work up to the harder ones.
Company type
Product
Headquarters
Sydney, Australia
Main India offices
Bengaluru
Atlassian React JS interview process
Online coding assessment
Coding round
System design or data round
Values round
Hiring manager round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for AtlassianStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
Use vi.mock with a factory, then control return values per test.
import { vi } from 'vitest';
import { getProfile } from './api';
vi.mock('./api', () => ({
getProfile: vi.fn()
}));
test('shows name', async () => {
getProfile.mockResolvedValue({ name: 'Ravi' });
render(<Profile />);
expect(await screen.findByText('Ravi')).toBeInTheDocument();
});
In Jest, the same pattern uses jest.mock and jest.fn.
02
A cart page keeps the selected item object in state and also the items array. After editing the item's quantity, the details panel shows the old quantity. Why?
The selected item is a copy duplicated from the array, so updating the array does not update the copy. This breaks the single source of truth. Store only selectedId in state and derive the item during render: const selected = items.find(i => i.id === selectedId). Now there is one place where each item lives, and every view stays in sync automatically.
React escapes values in JSX by default, which protects against XSS. dangerouslySetInnerHTML bypasses this and inserts raw HTML, so if the content comes from users or an untrusted CMS, attackers can inject scripts. If you must render HTML, sanitise it first with a library like DOMPurify, restrict allowed tags, and add a Content Security Policy. Also never put user input into href attributes without validating the protocol.
05
What is useId and why not use Math.random for ids?
useId generates a unique, stable id for a component instance that matches between server and client rendering. It is used for accessibility attributes, like linking a label's htmlFor to an input's id. Math.random or a global counter would produce different values on the server and the browser, causing hydration mismatches, and would change on every render. useId should not be used as list keys.
06
Write a custom hook to fetch data with loading and error states.
Use jest-axe or vitest-axe to run axe-core on rendered components.
import { axe } from 'vitest-axe';
test('form has no a11y violations', async () => {
const { container } = render(<SignupForm />);
expect(await axe(container)).toHaveNoViolations();
});
Also query by role and label in tests, run Lighthouse or axe DevTools in the browser, and test keyboard navigation manually, since automated tools catch only part of the issues.
08
A junior notices that every child component re-renders when the parent's state changes, even when their props did not change. How do you explain this?
By default, when a component renders, React re-renders all of its children, because it cannot know whether they depend on something else. Re-rendering is usually cheap since only real changes reach the DOM. If a child is expensive, wrap it in React.memo and keep its props stable with useCallback or useMemo, or let the React Compiler memoise automatically. Moving state down also helps.
09
Your React app works locally, but after deployment refreshing /dashboard gives a 404 from the server. Why, and how do you fix it?
The server looks for a real file at /dashboard, which does not exist because routing happens in the browser. Configure the server to return index.html for all unknown paths: a rewrite rule in Nginx (try_files $uri /index.html), a _redirects or rewrites setting on static hosts, or a fallback in Express. Alternatively, use a framework with server routing. HashRouter also avoids it but gives ugly URLs.
10
A developer sends an analytics event inside a useEffect that watches a 'submitted' state flag. Is this a good pattern?
No. Logic caused by a specific user action belongs in the event handler, not in an effect. Setting a flag and reacting in an effect adds an extra render, is harder to follow and can fire again on remount in StrictMode. Call sendAnalytics directly in handleSubmit. Effects are for synchronising with external systems because the component is displayed, not for responding to events.
Debouncing delays a value until the user stops typing, which reduces API calls.
function useDebounce(value, delay = 400) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const t = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(t);
}, [value, delay]);
return debounced;
}
const q = useDebounce(searchText);
// fetch when q changes
12
Your team uses the array index as key in a todo list and users report that checkboxes get ticked on the wrong item after deleting a row. What is happening?
When an item is deleted, every later item shifts to a new index, so React matches old state and DOM nodes to the wrong items. Uncontrolled inputs and component state stay attached to the index, not the data. The fix is to use a stable unique id from the data as the key. Index keys are only safe for static lists that never reorder, filter or delete.
RTK Query is the data fetching and caching tool included in Redux Toolkit. You define an API with createApi and endpoints, and it auto-generates hooks like useGetProductsQuery and useAddProductMutation. It handles loading states, caching, deduplicating requests, refetching and cache invalidation through tags. It removes most hand-written thunks and reducers for server data in Redux-based apps.
14
How do you type props for a component in TypeScript?
A new random key on every render tells React each item is brand new, so it unmounts and remounts every row each time. This destroys component state such as typed input and focus, re-runs effects and is very slow for large lists. Keys must be stable and unique, ideally an id from the data. If items have no id, generate ids once when the data is created.
16
Five components on one page each fetch the same user profile, causing duplicate API calls. How would you fix this?
Lift the data fetching into a shared cache instead of each component fetching on its own. With TanStack Query or RTK Query, all components using the same query key share one request and one cached result, and get updates together. Alternatively, fetch once in a parent or route loader and pass data down. This also removes inconsistent loading spinners across the page.
useSyncExternalStore subscribes a component to an external, non-React data source, like a browser API or a custom store, in a way that is safe with concurrent rendering. You give it a subscribe function and a getSnapshot function, and optionally getServerSnapshot. It prevents tearing, where parts of the UI show different values of the same store. Libraries like Redux and Zustand use it internally.
18
You inherit an old Redux codebase with connect, hand-written action types and switch reducers. How would you modernise it?
I would migrate gradually, not in one big rewrite. First replace createStore with configureStore, which keeps old reducers working. Then convert one feature at a time to createSlice, switch components from connect to useSelector and useDispatch, and move data fetching to RTK Query. Add tests around each feature before migrating, and remove dead actions. Each step ships independently and reduces risk.
19
Your team's old codebase uses PropTypes and is upgrading to React 19. What would you recommend for checking prop types?
PropTypes checks props at runtime in development and was removed from the React package in React 19, so it now needs the separate prop-types library and is ignored silently. TypeScript checks types at compile time, gives editor autocompletion, and catches errors before code runs. Most new React projects in India and abroad use TypeScript, and many job descriptions now list it as required.
20
How do you fetch data in a Next.js App Router page?
Make the page an async Server Component and await data directly.
// app/products/[id]/page.tsx
export default async function ProductPage({ params }) {
const { id } = await params;
const product = await getProduct(id);
if (!product) notFound();
return (
<main>
<h1>{product.name}</h1>
<AddToCartButton id={id} />
</main>
);
}
AddToCartButton is a Client Component. In recent Next.js versions params is a promise.
21
A timer using setInterval inside useEffect always shows 1 and never goes higher. What is the bug?
The effect probably runs once with an empty dependency array and calls setCount(count + 1). The interval callback closes over the count from the first render, which is 0 forever, a stale closure. Fix it with the updater form setCount(c => c + 1), so the callback never needs the current value, and return a cleanup that calls clearInterval to avoid leaks.
22
After adding an AuthContext at the root, profiling shows the whole app re-rendering every few seconds. What would you check?
Check what the provider value is and what updates it. Likely the value is a new object each render, or it includes fast-changing data such as a token refresh timer or a clock. Memoise the value with useMemo, move frequently changing data out of the context, and split it into separate contexts, so components reading only the user do not re-render when unrelated fields change.
A portal renders children into a DOM node outside the parent component's DOM hierarchy while keeping them in the same React tree, so context and event bubbling still work.
import { createPortal } from 'react-dom';
function Modal({ children }) {
return createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root')
);
}
They are used for modals, tooltips and dropdowns that must escape overflow hidden or z-index issues.
24
Why does React prefer composition over inheritance?
React reuses UI by combining components, not by extending classes. You pass components or JSX as props or children, so a generic Card or Modal can wrap any content. Specialisation is done by configuring a general component with props, like <Button variant='danger'>. The React team found no use cases where inheritance hierarchies were better, and composition keeps components flexible and loosely coupled.
25
In development your API call inside useEffect fires twice, but only once in production. Why does this happen, and what does StrictMode do?
StrictMode is a development-only wrapper that helps find bugs. It renders components twice to catch impure rendering, and mounts, unmounts and remounts components to check that effects clean up properly. This is why a fetch in useEffect may appear to fire twice locally. It does not happen in production. The fix is to write proper cleanup, not to remove StrictMode.
26
During a security review you find a payment provider's secret key in the browser's JavaScript bundle. What do you do?
Treat it as leaked: rotate the key immediately in the provider dashboard and check logs for misuse. Then fix the cause, usually the secret was in a public env variable such as NEXT_PUBLIC_ or VITE_, or imported into a client component. Move the call to a server route or Server Function that uses a server-only variable, add the server-only package to guard imports, and add secret scanning in CI.
27
Why normalise state in Redux and what does createEntityAdapter do?
Normalising means storing items in a lookup like { ids: [...], entities: { id: item } } instead of nested arrays. Each item exists once, updates are O(1) and you avoid duplicated data getting out of sync. createEntityAdapter in Redux Toolkit generates this structure plus reducers like addOne, upsertMany and removeOne, and memoised selectors such as selectAll and selectById.
Batching means React groups several state updates into one re-render. Before React 18 this only happened inside React event handlers. With createRoot, updates inside promises, setTimeout and native event handlers are also batched automatically. This reduces unnecessary renders. If you truly need a synchronous DOM update in between, you can use flushSync from react-dom, but that is rarely needed.
29
A search box fetches results on every keystroke and sometimes shows results for an older query. How do you fix this race condition?
Responses can arrive out of order, so a slow old request overwrites newer results. Cancel or ignore stale requests in the effect cleanup.
useEffect(() => {
const ctrl = new AbortController();
fetch(`/api/search?q=${q}`, { signal: ctrl.signal })
.then(r => r.json())
.then(setResults)
.catch(() => {});
return () => ctrl.abort();
}, [q]);
Also debounce the input, or use TanStack Query which handles this for you.
30
An orders table renders 10,000 rows and the page freezes on load and scroll. What would you do?
First question whether users need all rows at once: server-side pagination or infinite scroll with cursor-based loading may solve it. If a long scrollable list is required, virtualise it with TanStack Virtual so only around 30 rows exist in the DOM. Also memoise row components, avoid heavy formatting in render by precomputing, and move sorting or filtering off the main thread if it is expensive.
Tips to crack the Atlassian React JS interview
Read Atlassian's company values, such as Don't #@!% the Customer and Open Company, No Bullshit, for the values interview.
Use Jira and Confluence hands-on so you can discuss workflows, agile boards and possible product improvements.
Practise writing clean, well-structured code, as Atlassian coding rounds often value code quality and testing, not just correctness.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; Atlassian interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Atlassian React JS interview?
Candidates usually go through 5 stages: Online coding assessment; Coding round; System design or data round; Values round; Hiring manager round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the Atlassian React JS interview?
This practice set leans on React Hooks (6), Props and State (5), React Fundamentals (5), State Management (5). Revise those first, then practise explaining one or two of your own projects end to end, because most Atlassian interviewers ask you to walk through real work.
Are these the exact questions asked at Atlassian?
No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Atlassian's. They are not a leaked or verified list of past questions.
Where does Atlassian hire React JS professionals in India?
Atlassian has large teams in Bengaluru. Openings and locations change often, so check the Atlassian careers page and filter by city and experience.