Back to React episodes

React · Episode 6

Modernizing React Without Breaking Production: Legacy Apps, Server Components, Actions, Performance, and Security today

A long-form React podcast episode about modernizing existing React applications today without rewriting everything or breaking production. The episode covers React 19, Actions, useActionState, useOptimistic, Server Components, Client Components, framework migrations, legacy code, state management, routing, forms, design systems, accessibility, performance budgets, hydration, resource loading, metadata, testing, observability, security after React Server Components vulnerabilities, dependency discipline, AI-assisted refactoring, and practical modernization habits for real teams.

HostMichael A.Lead Full-Stack Engineer - Web3, Cloud and Mobile Platforms

GuestElena Brooks — Frontend Modernization Consultant — Brightline Engineering

Modernizing React Without Breaking Production: Legacy Apps, Server Components, Actions, Performance, and Security today

#6: Modernizing React Without Breaking Production: Legacy Apps, Server Components, Actions, Performance, and Security today

Original editorial from Softaims, published in a podcast-style layout—details, show notes, timestamps, and transcript—so the guidance is easy to scan and reference. The host is a developer from our verified network with experience in this stack; the full text is reviewed and edited for accuracy and clarity before it goes live.

Details

This is episode 6 of the React podcast category.

The episode keeps the same React stack topic but uses a new modernization and migration angle.

The discussion focuses on how teams can modernize existing React applications safely instead of chasing rewrites, hype, or fragile migrations.

The episode covers React 19, Server Components, Actions, forms, legacy React patterns, routing, state ownership, performance, testing, observability, security, design systems, accessibility, and AI-assisted refactoring.

The transcript is intentionally long, detailed, natural, and structured to feel like a 55-minute edited podcast conversation.

Show notes

  • Why modernization is harder than starting a new React app
  • The difference between a React upgrade and a React rewrite
  • How React 19 changes modernization planning
  • Actions, useActionState, useOptimistic, and modern form flows
  • Server Components and Client Components in existing applications
  • Framework migrations and when not to migrate
  • Routing cleanup and URL state discipline
  • State ownership: local, server, URL, form, global, and derived state
  • Design systems as a safe modernization path
  • Accessibility improvements during refactoring
  • Performance modernization: JavaScript weight, hydration, resources, and real user metrics
  • Testing before migration: behavior tests, integration tests, and critical flows
  • Frontend observability for safe incremental rollout
  • Security after React Server Components vulnerabilities
  • Dependency discipline, lockfiles, advisories, and patch readiness
  • AI-assisted refactoring without losing architectural control
  • A practical React modernization checklist for today

Timestamps

  • 0:00Cold open: modernization is not the same as rewriting
  • 3:30Why React teams inherit more than code
  • 7:00Audit first: understand the current app before changing it
  • 11:30React 19 and what actually matters for modernization
  • 16:00Modern forms with Actions, useActionState, and optimistic UI
  • 21:30Server Components in existing apps
  • 27:00Routing, URL state, and navigation cleanup
  • 31:30State management modernization without chaos
  • 36:00Design systems and accessibility as migration tools
  • 41:00Performance modernization: bundles, hydration, resources, and metadata
  • 46:00Testing, observability, and safe rollout
  • 50:00Security, RSC advisories, and dependency discipline
  • 53:00AI-assisted modernization
  • 54:30Final modernization checklist
  • 55:00End

Transcript

[0:00]Michael: Welcome back to the React stack podcast. This is episode six, and today we are talking about something almost every successful React team eventually faces: modernization. Not the fun kind of modernization where you open a blank repository, pick the newest framework, install the latest packages, and pretend the past does not exist. I mean the real kind. The kind where the app already has customers, old routes, old state patterns, old dependencies, old tests that may or may not be useful, a design system that is half adopted, and a business that still expects features to ship while the engineering team cleans up the foundation.

[0:58]Michael: Modernizing React is not the same as rewriting React. That distinction matters. Rewriting sounds clean. You imagine a new app with perfect architecture, fresh dependencies, modern routing, Server Components where they make sense, Actions for forms, a proper design system, better tests, clean state ownership, and no weird old files with names like finalFinalDashboardCopy. But rewrites are expensive, risky, and often dishonest about how much product behavior the old app actually contains.

[1:58]Michael: A real React application carries history. Some of that history is technical. Some of it is product behavior. Some of it is customer-specific edge cases. Some of it is old security assumptions. Some of it is undocumented design logic. If you throw everything away too quickly, you may remove bugs, but you may also remove behavior people rely on. So today we are asking a practical question: how do teams modernize React today without breaking production?

[2:55]Michael: We will talk about React 19, Actions, useActionState, useOptimistic, Server Components, framework migrations, routing cleanup, state management, design systems, accessibility, performance, observability, testing, security after the React Server Components vulnerability, dependency discipline, and AI-assisted refactoring. But the center of the episode is judgment. Modernization is not about using every new thing. It is about making the system safer, clearer, faster, and easier to change.

[3:30]Michael: To help us break this down, I am joined by Elena Brooks, frontend modernization consultant at Brightline Engineering. Elena works with teams that have real React applications already in production. She helps them migrate frameworks, update React versions, clean up component systems, reduce bundle size, improve accessibility, and build safer release habits. Elena, welcome.

[4:05]Elena Brooks: Thanks for having me. I like that you started with the difference between modernization and rewriting. A lot of teams say modernization when they really mean escape. They are tired of the old codebase, so they imagine a clean rewrite. Sometimes a rewrite is justified, but most of the time the better path is incremental modernization. You improve the system while it keeps serving users.

[4:58]Michael: Why do rewrites feel so tempting?

[5:02]Elena Brooks: Because old code has emotional weight. Developers remember the painful parts. They remember the confusing state store, the fragile routes, the weird form library, the dashboard nobody wants to touch, the component that has twenty props, and the dependency that blocks upgrades. A new app feels like freedom. But the old app also contains years of product decisions. Some are bad, but some are essential. A rewrite often underestimates that hidden knowledge.

[5:58]Michael: So modernization starts with respect for the existing system, even if the system is messy.

[6:05]Elena Brooks: Exactly. Respect does not mean defending bad architecture. It means understanding why things exist before changing them. A confusing component may be confusing because it grew without boundaries. But it may also handle three customer exceptions, two accessibility fixes, one browser quirk, and a compliance requirement nobody remembers. If you replace it without understanding that, you can create a beautiful regression.

[7:00]Michael: Let us start with the first step. Before a team upgrades, migrates, or introduces new React patterns, what should they audit?

[7:12]Elena Brooks: They should audit five things. First, runtime and dependency health: React version, framework version, bundler, TypeScript version, package manager, lockfile, and known vulnerabilities. Second, architecture shape: routing, data loading, state management, styling, forms, and design system usage. Third, product risk: which flows are business-critical, which customers use them, and which flows are fragile. Fourth, test confidence: what is covered, what is not, and which tests are trusted. Fifth, production visibility: can the team see errors, performance regressions, failed requests, and release impact?

[8:22]Michael: That sounds less glamorous than installing the new version.

[8:28]Elena Brooks: It is less glamorous, but it is what prevents panic. Modernization without an audit is guessing. You do not know whether the app is blocked by dependencies, by framework assumptions, by test gaps, by browser support, by old state patterns, or by missing observability. Teams often jump straight into migration work and then discover halfway through that they cannot tell if they broke anything.

[9:25]Michael: What is a good practical output from that audit?

[9:32]Elena Brooks: A modernization map. Not a huge document nobody reads, but a clear map. Here are the critical flows. Here are the risky dependencies. Here are the outdated patterns. Here are the safe areas to change first. Here are the areas that need tests before refactoring. Here are the performance hotspots. Here are the accessibility gaps. Here are the upgrade blockers. That map turns modernization from a vague ambition into a sequence of decisions.

[10:35]Michael: So the first modernization step may be adding tests and observability, not touching React code.

[10:42]Elena Brooks: Yes. If the team cannot detect breakage, the first job is detection. Before you replace a routing system, upgrade a framework, or refactor forms, you need to know whether users can still sign in, pay, search, save, invite, delete, export, or whatever the product actually does. Confidence comes before movement.

[11:30]Michael: Let us bring React 19 into this. React 19 is a major reference point for modern React. What parts matter most when modernizing an existing app?

[11:45]Elena Brooks: The most practical pieces are Actions, useActionState, useOptimistic, form Actions, metadata handling, resource APIs, and Server Components where the framework supports them. But I would not tell a team to adopt all of that everywhere. I would ask where the old app is painful. Are forms full of scattered loading and error state? Actions may help. Are some pages shipping too much client JavaScript for mostly read-only content? Server Components may help if the framework path is realistic. Are resource loading and metadata handled inconsistently? The newer APIs and framework conventions may help.

[12:55]Michael: So modern React features should solve real migration problems.

[13:00]Elena Brooks: Exactly. The mistake is feature-driven migration. A team hears about Server Components and tries to restructure the whole app around them. Or they hear about Actions and decide every mutation must be rewritten immediately. That creates risk without a clear payoff. Modernization should be pain-driven and value-driven. Start where the current app is hardest to maintain, slowest for users, or most fragile in production.

[14:05]Michael: What about teams still on older React patterns: class components, older context usage, effects everywhere, maybe old lifecycle methods?

[14:15]Elena Brooks: Do not panic. Old does not automatically mean broken. The question is whether the old pattern blocks change, creates bugs, prevents upgrades, or makes the product worse. Class components can be migrated gradually. Effects can be cleaned up when they cause real problems. Context can be narrowed when it is overused. The goal is not to erase history for aesthetic reasons. The goal is to reduce risk and improve clarity.

[15:15]Michael: That is probably hard for engineers who love clean code.

[15:20]Elena Brooks: It is. Clean code matters, but product safety matters more. Refactoring is good when it makes behavior safer or future work easier. Refactoring is risky when it changes a lot without measurable benefit. A mature React team knows the difference between improving architecture and satisfying personal taste.

[16:00]Michael: Let us talk about forms. Existing React apps often have messy forms. Some use custom hooks, some use old libraries, some have validation in components, some in schemas, some on the server, and some nowhere. How should modernization approach forms?

[16:20]Elena Brooks: Forms are one of the best modernization targets because users feel form quality directly. Start by identifying the critical forms: signup, login, checkout, billing, account settings, invite flows, content creation, admin actions, permission changes. Then look at the user experience. Does the form preserve input after errors? Are field errors clear? Does it show pending state? Does it prevent duplicate submission? Does it support keyboard users? Does it announce errors? Does it recover from server failure?

[17:28]Michael: Where do Actions and useActionState fit?

[17:35]Elena Brooks: They fit when a form is really an async transition. The user submits, the server validates, the result comes back, and the UI needs to reflect that result. useActionState can make the returned result part of the form state. Instead of five scattered booleans and three effects, the form can have a clearer action-driven model. That does not mean every old form must be rewritten immediately, but it gives teams a better target pattern for new and refactored forms.

[18:45]Michael: What about useOptimistic?

[18:50]Elena Brooks: useOptimistic is useful for low-risk, reversible interactions: comments, likes, task completion, small list updates, ordering, maybe draft UI. In modernization, it can replace homemade optimistic logic that grew messy over time. But teams need to be careful. Do not make high-risk operations appear complete before they are confirmed. Payments, permission changes, legal submissions, security settings, and destructive actions need more conservative feedback.

[20:00]Michael: So form modernization is partly technical and partly language.

[20:05]Elena Brooks: Yes. The words on the screen matter. Saving, saved, failed, retry, pending approval, submitted, processing, queued, scheduled. These words carry promises. A modern React form should not just have cleaner code. It should communicate honestly. If the system has not confirmed something, the UI should not pretend that it has.

[21:00]Michael: What is a simple form modernization sequence?

[21:05]Elena Brooks: First, add behavior tests around the existing critical form. Second, fix obvious accessibility and recovery issues. Third, standardize the shape of validation errors and server responses if possible. Fourth, introduce a modern action-driven pattern in one or two forms. Fifth, document the pattern and migrate other forms as they are touched. That is safer than rewriting every form in one sprint.

[21:30]Michael: Server Components are one of the biggest changes in modern React. How should teams think about them when they already have a client-heavy app?

[21:45]Elena Brooks: Carefully. Server Components can be valuable, but they are not a small refactor in every stack. They depend on framework integration and they change how teams think about the server-client boundary. For an existing client-heavy app, I would start by identifying pages that are mostly read-only, data-heavy, or expensive to ship as client JavaScript. Product pages, documentation, account summaries, dashboards with read-only sections, reports, and marketing pages may be candidates.

[22:55]Michael: What should not be the first Server Components target?

[23:00]Elena Brooks: Do not start with the most interactive, most fragile, most business-critical flow unless the team has strong support and tests. A complex checkout, rich editor, drag-and-drop workspace, or real-time collaboration view is probably not the first place to experiment. Start with something valuable but contained. Learn the model. Learn the framework behavior. Learn the caching and serialization rules. Then expand.

[24:05]Michael: What does the server-client boundary change for developers?

[24:12]Elena Brooks: It forces developers to ask where code runs. A Server Component can access server-only resources, but it cannot use browser-only APIs or client event handlers. A Client Component can handle interaction, but anything passed into it is serialized to the browser. That means data boundaries become more explicit. This is good, but only if the team understands it. Otherwise they get confusing errors or, worse, accidental data exposure.

[25:20]Michael: So Server Components are both a performance opportunity and a security responsibility.

[25:28]Elena Brooks: Exactly. They can reduce JavaScript and keep server-only logic away from the client. But they also mean React is operating closer to server concerns. Teams must patch framework integrations, understand payloads, avoid leaking sensitive data, and treat the server boundary seriously. The 2025 vulnerability made that very clear.

[26:30]Michael: What is a healthy adoption pattern?

[26:35]Elena Brooks: Use a pilot. Pick a route with clear value and manageable risk. Measure before and after: JavaScript size, load time, interaction readiness, error rate, and developer complexity. Document what changed. Decide whether the model is worth expanding. Modernization should create evidence, not just opinions.

[27:00]Michael: Routing cleanup is another modernization area. Existing React apps often have routing that grew over years. What do you look for first?

[27:15]Elena Brooks: I look for route ownership and URL behavior. Which routes are public? Which are authenticated? Which require permissions? Which have nested layouts? Which use query parameters for view state? Which lose state on refresh? Which duplicate loading and error handling? Which routes have special redirects or legacy URLs? Routing is product structure, so cleaning it up can make the whole app feel more stable.

[28:20]Michael: What is a common URL state problem?

[28:25]Elena Brooks: Filters, tabs, search terms, pagination, and selected views living only in component state. Users filter a table, click into a detail page, go back, and lose everything. Or they refresh and the view resets. Or they share a link and the teammate sees a different view. Moving meaningful view state into the URL can be a simple modernization with a big product payoff.

[29:30]Michael: Does every state belong in the URL?

[29:35]Elena Brooks: No. Temporary UI state like a dropdown being open usually does not. But if the state represents navigation, filtering, search, pagination, selected entity, or shareable context, the URL deserves consideration. Modernization is not about making everything complicated. It is about matching state to user expectations.

[30:35]Michael: How do you clean routing without breaking everything?

[30:40]Elena Brooks: Preserve old URLs with redirects where needed. Add tests around important navigation flows. Improve one route group at a time. Standardize route-level loading and error states. Move repeated layouts into shared route layouts if the framework supports it. Track analytics so you know whether users still reach key flows. Routing changes feel simple, but they can break bookmarks, emails, search results, and customer workflows.

[31:30]Michael: State management modernization. This is where teams can get religious. How do you keep it practical?

[31:42]Elena Brooks: Classify state before choosing tools. Local UI state belongs close to the component. Server state needs freshness, caching, invalidation, loading, and error handling. URL state represents navigation or shareable view context. Form state represents what the user is editing. Global state is for truly cross-cutting concerns. Derived state should usually be calculated, not stored.

[32:45]Michael: What does modernization look like if a team has one giant global store?

[32:52]Elena Brooks: Do not rip it out all at once. First, identify what is actually in it. Some of it may be server data. Some may be UI state. Some may be form drafts. Some may be user session display data. Some may be derived values. Then remove categories gradually. Move server data to a server-state layer or framework data pattern. Move URL state into the URL. Move local UI state back into components. Keep truly global state global. The goal is to shrink the store until it has a clear purpose.

[34:05]Michael: What is the biggest risk during state refactoring?

[34:10]Elena Brooks: Breaking invisible behavior. A store may be messy, but other parts of the app may rely on its side effects, subscriptions, persistence, or update timing. Before refactoring, add tests around key flows and observe production behavior. State refactors often look mechanical, but they can change timing and data freshness in subtle ways.

[35:10]Michael: What about derived state?

[35:15]Elena Brooks: Derived state is a common modernization win. If the app stores values that can be calculated from existing truth, you can often remove synchronization bugs by calculating instead. For example, cart totals, filtered lists, counts, display labels, or permission summaries may not need separate storage. But be practical. If calculation is expensive or needed for a specific performance reason, memoization or caching may be appropriate. The principle is: avoid duplicate truth unless you have a reason.

[36:00]Michael: Design systems. You often describe design systems as modernization tools. Why?

[36:12]Elena Brooks: Because a design system lets you modernize repeated behavior once and spread it safely. If every screen has its own button, field, modal, menu, table, alert, and loading state, modernization becomes endless. But if you improve the shared components, you can improve accessibility, consistency, styling, keyboard support, focus behavior, loading states, and error states across many flows.

[37:15]Michael: That sounds like a safer path than rewriting screens one by one.

[37:20]Elena Brooks: It can be. For example, modernizing a Dialog component to handle focus correctly can improve many parts of the app. Modernizing a FormField component to connect labels, descriptions, and errors can improve many forms. Modernizing a Button component to handle loading and disabled states consistently can remove dozens of one-off patterns. A good design system turns modernization into leverage.

[38:25]Michael: Where do design system migrations go wrong?

[38:32]Elena Brooks: They go wrong when the design system is built like a separate perfect world and then thrown at product teams. If it does not support real product needs, teams will bypass it. If migration requires rewriting every screen manually, it will stall. If accessibility is treated as optional, the system spreads weak behavior. The best design system migrations provide strong defaults, clear docs, codemods where possible, examples, and escape hatches that are reviewed rather than forbidden.

[39:42]Michael: Accessibility modernization is often overdue in legacy React apps. Where should teams begin?

[39:50]Elena Brooks: Start with critical flows and shared components. Can users navigate with a keyboard? Are focus states visible? Are form controls labeled? Are errors connected to fields? Do dialogs manage focus? Is important meaning conveyed only by color? Does reduced motion work? Do route changes leave focus somewhere sensible? Automated checks help, but manual testing is essential.

[40:48]Michael: So modernization is a chance to fix quality debt, not just dependency debt.

[40:55]Elena Brooks: Exactly. A React app can be on the latest version and still be inaccessible, slow, confusing, and fragile. Version modernization is only one part. Product quality modernization matters more to users.

[41:00]Michael: Performance modernization. Where do old React apps usually carry performance debt?

[41:15]Elena Brooks: Large client bundles, old dependencies, duplicated component libraries, too much global state, unoptimized images, heavy charts, expensive rendering, unnecessary hydration, network waterfalls, blocking fonts, third-party scripts, and routes that load everything before showing anything. Sometimes the app feels slow not because React is slow, but because the architecture asks the browser to do too much at once.

[42:25]Michael: What should teams measure before making changes?

[42:30]Elena Brooks: Measure JavaScript size per route, route load time, interaction responsiveness, hydration cost, network waterfalls, image weight, server response time, error rate, and real user metrics. Also measure important flows, not just home page metrics. A dashboard app may not care as much about a marketing landing page, but it may care deeply about the reports route or billing route.

[43:35]Michael: How do React 19 resource APIs fit into modernization?

[43:42]Elena Brooks: They help teams express resource priority more clearly. preconnect, preload, preinit, and prefetchDNS can help the browser prepare important resources earlier when used carefully. But modernization teams should avoid cargo-cult preloading. Do not add resource hints everywhere. Use them where measurement shows a critical resource or connection is delaying the experience.

[44:45]Michael: What about metadata?

[44:50]Elena Brooks: Old apps often handle metadata inconsistently. Titles, descriptions, social previews, canonical links, and route-level metadata may be missing or scattered. Modern React and framework patterns can make metadata more structured. That matters for public pages, but also for usability. Good titles help users understand where they are, especially with multiple tabs or assistive technology.

[45:45]Michael: What is a practical performance modernization sequence?

[45:50]Elena Brooks: First, measure real user pain. Second, remove obvious waste: duplicate dependencies, unused packages, oversized assets, unnecessary polyfills, and routes importing too much. Third, split code by route or interaction. Fourth, consider server rendering or Server Components where they reduce client cost. Fifth, watch production after each change. Performance modernization should be gradual because regressions can hide in specific devices, browsers, or customer data shapes.

[46:00]Michael: Testing and observability are the safety net for all of this. What should be in place before major modernization?

[46:15]Elena Brooks: At minimum, behavior tests for critical flows, integration tests around routing and data where risk is high, accessibility checks for shared components, and end-to-end tests for journeys that the business cannot afford to break. But tests are only half the story. You also need production observability: client errors, release versions, route context, failed requests, performance metrics, feature flag context, and source maps managed safely.

[47:25]Michael: Why do tests alone not solve modernization risk?

[47:32]Elena Brooks: Because tests reflect what the team thought to test. Production reflects what users actually do. A migration may pass tests and still fail for a browser version, a permission combination, a slow network, a customer with unusual data, or a feature flag mix nobody tested. Observability catches reality.

[48:35]Michael: How should teams roll out risky changes?

[48:40]Elena Brooks: Use small releases, feature flags when appropriate, route-by-route migration, canary users, internal dogfooding, staged rollout, and clear rollback paths. Do not combine a React upgrade, framework migration, design system replacement, state refactor, and routing rewrite in one release unless you enjoy pain. The safest modernization is boring modernization.

[49:42]Michael: Boring modernization sounds like a good slogan.

[49:48]Elena Brooks: It is. Boring means controlled. Boring means observable. Boring means reversible. Users should not feel your modernization except through a better product.

[50:00]Michael: Security. The React Server Components vulnerability in December 2025 changed how many teams think about modern React. What should modernization teams learn from it?

[50:18]Elena Brooks: The lesson is that modern React dependencies can be part of the server attack surface. If your app uses Server Components, framework server functions, or packages like react-server-dom integrations, security updates are not optional maintenance. They are production safety. Teams need to know which packages are deployed, which versions are affected, and how quickly they can patch.

[51:20]Michael: What security habits should be part of modernization?

[51:25]Elena Brooks: Use lockfiles. Keep React, framework, and bundler dependencies updated. Monitor security advisories. Avoid unnecessary packages. Review packages that run on the server more carefully. Keep secrets on the server. Treat serialized data as visible to the client. Sanitize untrusted HTML. Do authorization on the server, not only in the UI. Practice emergency patching before a real emergency.

[52:30]Michael: So modernization includes patch readiness.

[52:35]Elena Brooks: Absolutely. A team may say they want modern React, but if they cannot ship a critical security update quickly, they are not operationally modern. Modernization is not only code style. It is release capability.

[53:00]Michael: AI-assisted modernization. This is a big one. Teams are using AI to refactor components, migrate code, generate tests, and explain old files. Helpful or dangerous?

[53:12]Elena Brooks: Both. AI is very helpful for creating migration checklists, drafting tests, converting repetitive patterns, explaining legacy components, suggesting codemod strategies, generating Storybook examples, and identifying accessibility issues. But it can also confidently produce wrong code. It may miss product behavior, server-client boundaries, security assumptions, or accessibility details. It may rewrite something that looked ugly but handled a real edge case.

[54:05]Michael: What is the safe way to use AI here?

[54:10]Elena Brooks: Use AI for acceleration, not authority. Give it context. Ask it to propose changes, not silently apply them. Review diffs carefully. Run tests. Compare behavior. Be extra cautious with auth, permissions, server actions, data serialization, forms, payment flows, and dependencies. AI can help modernize React, but humans still own the product.

[54:30]Michael: Let us close with a checklist. A team wants to modernize a production React application today. What should they do?

[54:38]Elena Brooks: First, audit before changing. Second, protect critical flows with tests and observability. Third, upgrade dependencies deliberately and keep patching boring. Fourth, modernize forms where users feel pain, using Actions, useActionState, and useOptimistic when they clarify real async behavior. Fifth, pilot Server Components only where the framework and product shape make sense.

[54:50]Elena Brooks: Sixth, clean routing and URL state gradually. Seventh, shrink global state by classifying ownership. Eighth, use design systems to spread accessibility and consistency. Ninth, measure performance through user journeys. Tenth, use AI carefully, release incrementally, and remember that modernization should make production calmer, not more exciting.

[54:58]Michael: Final sentence: what is React modernization really about?

[54:59]Elena Brooks: React modernization is about improving the system users already depend on, without pretending the past can be deleted safely overnight.

[55:00]Michael: Elena Brooks, thanks for joining us. End.

More React Episodes