adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.77k stars 1.1k forks source link

[@react-aria/live-announcer] "Uncaught Error: document is not defined" when used in render function in SSR #6234

Open wojtekmaj opened 5 months ago

wojtekmaj commented 5 months ago

Provide a general summary of the issue here

When announce() is used in render function in SSR, it triggers an error: "Uncaught Error: document is not defined".

๐Ÿค” Expected Behavior?

announce() to abort if document is not defined

๐Ÿ˜ฏ Current Behavior

announce() attempts to create div using document.createElement even in Node.js environment

๐Ÿ’ Possible Solution

if (typeof document === 'undefined') {
  return;
}

๐Ÿ”ฆ Context

No response

๐Ÿ–ฅ๏ธ Steps to Reproduce

Run the following component in SSR:

function Search() {
  const searchParams = useSearchParams();
  const [searchQuery, setSearchQuery] = useState(searchParams.get('search'));

  const results = use(getResults());

  searchQuery && announce(`Found ${results.length} results`, 'polite');

  return <></>;
}

Version

3.34.1

What browsers are you seeing the problem on?

Other

If other, please specify.

Node.js

What operating system are you using?

macOS Ventura

๐Ÿงข Your Company/Team

No response

๐Ÿ•ท Tracking Issue

No response

snowystinger commented 5 months ago

Thanks for the issue!

I don't think you should use an announce in the render function, it has a side effect. I think you should put it inside an effect which wouldn't run on the server anyways. That, or put it in an interaction callback.

In addition, you may have this announced more times than you expect because you're relying on renders, which are not guaranteed and in React 18+ may actually run multiple times in their concurrent model. In an effect you can guard against extraneous calls.