Frontend Developer · Focus area 1: Advanced frameworks

FE2: Managing shared state

Goal: decide where each piece of information in an app should live and how screens share it: the kinds of state, React context, store libraries such as Zustand and Redux Toolkit, server data with a caching library, and the URL as state.

You'll need: your Kirana Express project from FE1, the state management ideas from Module 37, and a small fake API (a JSON file or a mock server) for products, cart and orders.

Where this is used: any app with more than one screen: a cart shown in the header and on the checkout page, a logged-in user shown everywhere, filters that should survive a page refresh. Getting state in the wrong place causes stale data, extra requests and bugs that only appear on some screens.

How it differs: a backend developer keeps one source of truth in a database. A frontend developer juggles several copies at once (what the server says, what the screen shows, what the user is typing) and must keep them in step without slowing the app.

Time: reading about 2 hours · practice (the Try it tasks) about 3 hours · assignment about 3 to 4 hours.

Lessons

  1. 1Kinds of state and where each livesReading 15–25 minutes, plus practice✓
  2. 2Context, and its costsReading 15–25 minutes, plus practice✓
  3. 3Stores: Zustand and Redux ToolkitReading 15–25 minutes, plus practice✓
  4. 4Server data with a caching libraryReading 15–25 minutes, plus practice✓
  5. 5The URL as stateReading 15–25 minutes, plus practice✓

🛠️Assignment: Shared state for the Kirana Express app

This sets up the state design for the multi-page app project.

  1. Write a state map of at least ten values with kind, home, refresh and sharing needs.
  2. Split any broad context into narrow ones, and measure renders before and after.
  3. Move the cart into a store with actions, selectors and safe persistence.
  4. Move server data into a caching library with chosen staleTimes, and add an order mutation with invalidation.
  5. Move search, filters, sort and page into the URL, validating values read from it.

Self-check before you finish:

✅Module check

Explain in a few sentences, in your own words:

How do you decide where each piece of state lives in a frontend app?

Show a good answer

A good answer mentions: the kinds of state (local UI, shared UI, server, URL, form) and asking who owns and needs each value; calculating derived values instead of storing copies; context for rarely changing shared values, split by how often they change; a store with actions and selectors for frequently changing shared state, updated without changing in place; a caching library for server data with staleTime, invalidation and optimistic updates; and the URL for refreshable, shareable state, without personal data.

📚Official references

Official documentation and guidance for this module's topics, chosen on 2 November 2026. Tools, laws and standards change, so check the current version before you rely on a detail. If a link has moved, search the same site.

📝Module quiz

10 questions · 10 marks each · 100 marks in all · pass mark 70% · retry as often as you like ·

1. A team keeps every input's text and every dialog's open state in one global store. Typing anywhere slows the app. What's the best fix?

Why each option is right or wrong

  • “Switch to a faster store library” (Incorrect): The problem is what's in the store, not the library.
  • “Debounce every input by one second” (Incorrect): That makes typing feel laggy and hides the design problem.
  • “Split the store file into many files” (Incorrect): The same state would still update the whole app.
  • “Keep local state in components” is correct.

    Text being typed and a dialog's open state are only needed by one component. Keeping them local means typing re-renders only that component. The store then holds just truly shared values.

    • Server data: move to a caching library.
    • Keep in store: cart, selected store, preferences.

📖 Revise: Lesson 1: Kinds of state and where each lives

Question ID sp-frontend-02-q1 · Report a mistake in this question
2. A cart total stored in its own state falls out of step when prices update. What's the fix?

Why each option is right or wrong

  • “Update the total in an effect whenever prices change” (Incorrect): That adds an extra render and can still show stale values briefly.
  • “Recalculate the total once a minute” (Incorrect): The total would be wrong for up to a minute.
  • “Store the total on the server only” (Incorrect): The screen needs it instantly as items change.
  • “Calculate it from items and prices when needed” is correct.

    The total is derived from other state. Calculating it during render means it can't disagree with the items and prices. useMemo helps only if the calculation is slow.

    • Rule: don't store what you can derive.
    • Test: change a price and check the total.

📖 Revise: Lesson 1: Kinds of state and where each lives

Question ID sp-frontend-02-q2 · Report a mistake in this question
3. An app has one AppContext with the user, theme and cart. Adding an item re-renders about 240 components. What should you do?

Why each option is right or wrong

  • “Remove context and pass props everywhere” (Incorrect): Passing props through many levels is tedious and doesn't reduce renders by itself.
  • “Wrap the whole app in memo” (Incorrect): memo doesn't stop components re-rendering when a context they read changes.
  • “Reload the cart from the server after each add” (Incorrect): That adds requests and still re-renders every reader.
  • “Split it into separate contexts” is correct.

    Every reader of a context re-renders when its value changes. Putting the user and theme (rarely change) apart from the cart (changes often), and having only cart-related components read the cart, cuts renders to the few that need them.

    • Also: keep each provided value stable with useMemo.
    • Or: a store with selectors for the cart.

📖 Revise: Lesson 2: Context, and its costs

Question ID sp-frontend-02-q3 · Report a mistake in this question
4. A countdown banner puts the current time, updated every second, in the app-wide context. Battery complaints arrive. What's the fix?

Why each option is right or wrong

  • “Update the time every 5 seconds instead” (Incorrect): That reduces the re-renders but still re-renders the whole app regularly.
  • “Move the countdown to the server” (Incorrect): The display still needs to tick on the device.
  • “Remove the countdown banner” (Incorrect): The banner can work fine with state in the right place.
  • “Keep the timer in the banner” is correct.

    Only the banner needs the ticking time. Holding it in the banner's own state means only the banner re-renders each second, and the rest of the app stays still.

    • Clean up: clear the interval when the banner leaves.
    • Check: the Profiler shows one component per tick.

📖 Revise: Lesson 2: Context, and its costs

Question ID sp-frontend-02-q4 · Report a mistake in this question
5. A store action does state.items.push(p); set({ items: state.items }), and the cart badge sometimes doesn't update. Why?

Why each option is right or wrong

  • “The store needs more memory” (Incorrect): Memory isn't the problem; the update pattern is.
  • “The badge needs a key” (Incorrect): Keys are for lists; the badge isn't receiving a new value.
  • “Zustand can't store arrays” (Incorrect): Stores handle arrays fine when updated correctly.
  • “The array was changed in place” is correct.

    Subscribers compare the new value with the old one. Pushing into the same array and setting it back means the reference doesn't change, so subscribers may not update. Returning a new array ([...items, p]) fixes it.

    • Rule: create new arrays and objects for updates.
    • Redux Toolkit: its helpers handle this for you.

📖 Revise: Lesson 3: Stores: Zustand and Redux Toolkit

Question ID sp-frontend-02-q5 · Report a mistake in this question
6. A two-person team is building a small shop app with one shared cart and a selected store. Which store approach fits best?

Why each option is right or wrong

  • “Redux Toolkit with many slices, to be ready for growth” (Incorrect): Its structure adds work this app doesn't need yet.
  • “A global variable in a separate file” (Incorrect): React won't re-render when a plain variable changes.
  • “Storing the cart only on the server” (Incorrect): Every tap would wait for the network.
  • “A small store such as Zustand” is correct.

    The shared state is small and the team is small. A lightweight store with a few actions and selectors keeps the code short while avoiding wide context re-renders.

    • Larger teams: Redux Toolkit's structure and tooling help.
    • Persist: cart items only.

📖 Revise: Lesson 3: Stores: Zustand and Redux Toolkit

Question ID sp-frontend-02-q6 · Report a mistake in this question
7. A checkout page still shows a customer's old delivery address after they edit it, until they refresh. Addresses come from a cached query. What's missing?

Why each option is right or wrong

  • “A longer staleTime for addresses” (Incorrect): That keeps the old data for longer.
  • “Turning off caching for the whole app” (Incorrect): Caching helps elsewhere; the address query just needs refreshing after the edit.
  • “Reloading the page after every edit” (Incorrect): Reloading loses state and feels slow.
  • “Invalidate the address query” is correct.

    The edit changed server data, but the cached copy wasn't told. Invalidating ['addresses'] when the mutation succeeds refetches it, and an optimistic update can show the change at once.

    • Rule: each mutation lists the queries it affects.
    • Test: edit, then check every screen that shows addresses.

📖 Revise: Lesson 4: Server data with a caching library

Question ID sp-frontend-02-q7 · Report a mistake in this question
8. Products change a few times a day; stock changes with every order. How should staleTime be set?

Why each option is right or wrong

  • “The same short time for both” (Incorrect): Products would refetch far more than needed.
  • “Zero for both, to be safe” (Incorrect): Every component mount would refetch, adding many requests.
  • “One hour for both, to save requests” (Incorrect): Stock would be out of date and customers would order items that ran out.
  • “Longer for products, short for stock” is correct.

    staleTime should match how fast the data changes. Products can stay fresh for minutes; stock needs seconds. That keeps stock accurate without refetching the catalogue constantly.

    • Example: 5 minutes and 10 seconds.
    • After an order: invalidate stock.

📖 Revise: Lesson 4: Server data with a caching library

Question ID sp-frontend-02-q8 · Report a mistake in this question
9. Customers complain that pressing back after viewing a product loses their search filters. Filters are kept in component state. What's the fix?

Why each option is right or wrong

  • “Save filters in localStorage” (Incorrect): That restores them, but links still can't be shared, and back and forward history won't match.
  • “Disable the back button on product pages” (Incorrect): That breaks normal browsing.
  • “Open products in a new tab” (Incorrect): That avoids the symptom and adds clutter.
  • “Store the search filters in the URL” is correct.

    URL state survives refresh, works with back and forward, and can be shared. Reading filters from ?q=atta&cat=staples restores the list exactly.

    • Validate: values read from the URL.
    • Bonus: analytics shows popular filters.

📖 Revise: Lesson 5: The URL as state

Question ID sp-frontend-02-q9 · Report a mistake in this question
10. A support dashboard puts ?phone=9876543210 in its URLs so searches can be shared. What's the problem, and the fix?

Why each option is right or wrong

  • “URLs can't hold numbers; encode it” (Incorrect): URLs can hold numbers; the issue is what kind of data it is.
  • “The URL is too long; shorten it” (Incorrect): Length isn't the problem.
  • “Sharing should be disabled entirely” (Incorrect): Shareable links are useful when they hold the right data.
  • “Personal data leaks; use an internal ID” is correct.

    URLs end up in browser history, server logs and analytics. Using an internal customer ID keeps links shareable for staff without spreading phone numbers. Existing analytics data should be cleaned.

    • Review: any new URL parameter.
    • Check: what analytics collects from URLs.

📖 Revise: Lesson 5: The URL as state

Question ID sp-frontend-02-q10 · Report a mistake in this question

ProLearners Assist