Where React's defaults protect you, and where they don't.
React escapes any value rendered as JSX content by default, which is why {userInput} rendered as text is safe even if that input contains HTML-looking characters — React treats it as plain text rather than parsing it as markup. That protection has one explicit, deliberately named opt-out: dangerouslySetInnerHTML bypasses escaping entirely and injects raw HTML, and the intentionally alarming name is meant to make you stop and think before reaching for it.
React's default escaping doesn't cover everything, though. A URL built from unsanitized user input and used in an href or src can still enable a javascript: URI injection, since that's not something JSX's text-escaping addresses. Third-party components or libraries that use dangerouslySetInnerHTML internally can reintroduce the same risk in code you don't directly control. And React apps still need everything any other web app needs — sanitizing data before it's stored, validating on the server since client-side validation can always be bypassed, and being deliberate about exactly what data an API sends down to the client in the first place.
What you'll walk away knowing