facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
225.55k stars 45.98k forks source link

[Bug] : SSR Suspense renders dollar sign ($) in the dom #29719

Open sarathjasrin opened 1 month ago

sarathjasrin commented 1 month ago

Hi I have tried to render a simple component via SSR. Which prints $ sign because of that Hydration is failing.

React version: 18.3.2

Steps To Reproduce

  1. App Component
import React, { useEffect } from 'react'

interface Props {}

const App: React.FC<Props> = () => {
  useEffect(() => {
    console.log('App component mounted')
  }, [])
  return (
    <div>
      <h1>Hello, React</h1>
    </div>
  )
}

export default App
  1. express router
router.get('*', (req, res) => {
      const Component = this.loadComponent(req.path)

      fs.readFile(
        path.resolve('./src/public/index.html'),
        'utf8',
        // eslint-disable-next-line consistent-return
        (error, data) => {
          if (error) {
            console.error(error)
            return res.status(500).send('An error occurred')
          }

          let didError = false

          const stream = renderToPipeableStream(
            <Suspense fallback={<div>Loading...</div>}>
              <Component />
            </Suspense>,
            {
              onShellReady() {
                res.statusCode = didError ? 500 : 200
                res.setHeader('Content-type', 'text/html')

                const initialHtml = data.replace(
                  '<div id="root"></div>',
                  '<div id="root">',
                )
                res.write(initialHtml)
                console.log(initialHtml)

                stream.pipe(res)
              },
              onShellError() {
                res.statusCode = 500
                res.send('<!doctype html><p>Loading...</p>')
              },
              onAllReady() {
                // If everything is ready, we end the stream
                if (!didError) {
                  res.end('</div></body></html>')
                }
              },
              onError(err) {
                didError = true
                console.error(err)
              },
            },
          )
        },
      )
    })

The current behavior

image

$RC is appended in the dom which inserts the $ sign

image

Link to code example:

The expected behavior

Should print Hello, React only once without any additional characters .

Riyazul555 commented 1 month ago

Hey @sarathjasrin can you elaborate a little bit where you want this behavior to be changed Thanks

sarathjasrin commented 1 month ago

Hi @Riyazul555 , thanks for the reply. I have explained everything above. Do you have any question particularly ?

Above you can see Hello react printing twice because of hibernation didn't work.

Riyazul555 commented 1 month ago

Hey @sarathjasrin I think I have understood why it's happening but I don't know which file I have to change in the repo.... little confused in that

In case the solution I can post it here.

sarathjasrin commented 1 month ago

@Riyazul555 Are you able to reproduce the bug? I don't know where the logic comes from