nfl / react-helmet

A document head manager for React
MIT License
17.28k stars 657 forks source link

Set boolean attributes as empty strings #619

Closed alexandermendes closed 3 years ago

alexandermendes commented 3 years ago

When using react-helmet with SSR we're seeing issues with elements being re-rendered in the browser due to the difference in how boolean attributes are rendered. This is especially problematic for async scripts, which can then run twice.

If we use renderToStaticMarkup() to render the server-side markup boolean attributes are rendered as empty strings, for example:

const el = React.createElement('script', { async: true });
console.log(ReactDOM.renderToStaticMarkup(el));
// => <script async=""></script>

https://github.com/facebook/react/blob/9198a5cec0936a21a5ba194a22fcbac03eba5d1d/packages/react-dom/src/client/DOMPropertyOperations.js#L187

Helmet uses Element.setAttribute() directly, without the extra stuff React does to modify these attributes, so boolean attributes are set as their stringified values, like:

const el = document.createElement('script');
el.setAttribute('async', true);
console.log(el);
// => <script async="true"></script>

It seems the difference between these two outputs is enough to cause the element to re-render.

CLAassistant commented 3 years ago

CLA assistant check
All committers have signed the CLA.

codecov[bot] commented 3 years ago

Codecov Report

Merging #619 into master will not change coverage. The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #619   +/-   ##
=======================================
  Coverage   96.90%   96.90%           
=======================================
  Files           3        3           
  Lines         291      291           
=======================================
  Hits          282      282           
  Misses          9        9           
Impacted Files Coverage Δ
src/HelmetUtils.js 96.87% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 1b57ddb...fdcdee3. Read the comment docs.