Server-rendered state can break out of its script tag
renderToStaticMarkup builds the HTML a server would send. In the first line the browser's HTML parser would end the script at the user's </script>, and whatever the user typed next would be parsed as page HTML. The second line can't be closed early, and JSON.parse still gives back the original text.
XSS happens when text from someone else is treated as code in your page. JSX escapes every string you put in text or attributes, so it always shows as text, but refs with innerHTML, dangerouslySetInnerHTML, unsafe URLs, spread props and server-rendered state can still let it in.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 5 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
A component shows a search term from the URL: div.innerHTML = 'Results for ' + q. Rewrite it safely in React.
Write a small helper serializeState(obj) that is safe to put inside <script type="application/json">, and show how the client reads it back.
Write a component that shows a user's name in bold inside a sentence ("Welcome back, Asha!") without using any HTML strings.
Explain it without notes
What is XSS, and what can an attacker do once their script runs in your page?
Exactly why is <p>{userText}</p> safe in React, both in the browser and in server rendering?
List the ways XSS can still get into a React app.
Why is putting JSON.stringify(data) inside a <script> tag dangerous, and how do you fix it?
Preview
Console
Nothing logged yet.Expected console output
<script id="state" type="application/json">{"user":"asha","bio":"I love </script> tags"}</script>
<script id="state" type="application/json">{"user":"asha","bio":"I love \u003c/script> tags"}</script>
after JSON.parse: I love </script> tags