vikejs / vike-react

🔨 React integration for Vike
https://vike.dev/vike-react
MIT License
94 stars 15 forks source link

New component hook `useDocument()` #67

Closed brillout closed 3 weeks ago

brillout commented 7 months ago
import { useDocument } from 'vike-react'

function MyComponent() {
  const document = useDocument()
  document.title = 'Awesome Product'
  document.head.add(
    <meta name="description" content="This product helps you with...">
  )
  // ...
}

It's particularly relevant when the data fetching logic is co-located with the component, for example when using Telefunc:

// /pages/product/@id/+Page.jsx
// Environement: client, server

import { loadProductInfo } from './Page.telefunc.js'
import { useDocument, usePageContext, useAsync } from 'vike-react'

function MyComponent() {
  const pageContext = usePageContext()
  const product = useAsync(() => loadProductInfo(pageContext.routeParams.id))
  const document = useDocument()
  document.title = product.name
  document.head.set(
    <meta name="description" content={product.description}>
  )
  // ...
}
// /pages/product/@id/Page.telfeunc.js
// Environement: server

export { loadProductInfo }

async function loadProductInfo(id) {
  const product = await sql.run(`SELECT { name, description } FROM products WHERE id = ${id};`)
  return prodcut
}

Some implementation details: https://github.com/vikejs/vike-react/issues/36#issuecomment-1842870621.

Related: https://github.com/vikejs/vike-react/issues/67.

brillout commented 6 months ago

Closing in favor of https://github.com/vikejs/vike-react/issues/88.

brillout commented 4 months ago

Re-opening because I believe this design to be superior to React 19's approach.

beku8 commented 4 months ago

Hello @brillout I've been trying to set the title & meta tags while using vike-react-query. I've tried something similar to your suggestion in #36

injectToStream(
  `<script>document.title = 'someTitleSetByAnyComponent'</script>`,
);

The main issue seems to be (as you commented) that this will not work for SEO/social bots. Setting title & descriptions are specifically useful only for SEO/Social bots. Imagine setting a meta tag like <meta property="og:image" content={data.imageUrl} /> so that people will see this image on the shared link previews, or providing correct descriptive title and meta tags for search engines.

Is it technically possible to implement useDocument() like you suggested here, but for when streaming is disabled?

brillout commented 4 months ago

@beku8 You can have a look at https://github.com/vikejs/vike-react/pull/108 which is the ongoing implementation of useDocument() among other things. See the changes made to /examples/full/.

It seamlessly works with React Query (because you can use useDocument() after RQ).

Streaming is automatically opted out if a bot is crawling the website, thus SEO & social sharing just works.

beku8 commented 4 months ago

@brillout thanks for the response. This looks beautiful, can't wait until it gets released.

FlorianCassayre commented 2 months ago

This hook would solve a limitation that I am encountering when using react-intl: in order to translate the title tag I need access to the intl context (useIntl), however this context is not available inside +Head.ts.

brillout commented 2 months ago

@FlorianCassayre Makes sense.

In the meantime a possible workaround is to use <Wrapper> to add your useIntl() provider. Although I think the wrapper currently only applies to Page and not to Head, so this would need to be changed e.g. with a new option Wrapper: { value: Component, head: boolean }.

FlorianCassayre commented 2 months ago

Thanks for the pointer; I'll try that out. In the meantime this is not a show stopper in my case, but I can totally see a use case for being able to modify the page title inside React components (while still keeping SSG capabilities). This is what sets <title/> (& favicon + language) apart from the other <head/> tags.

brillout commented 3 weeks ago

https://vike.dev/useConfig

Let us know if anything doesn't work for your use case. We look forward to gathering feedback on the new improvements to head tag management.

FlorianCassayre commented 3 weeks ago

Just tried it out (React) and works exactly as advertised, wonderful! This API makes a lot of sense and seems highly flexible. I'm updating my project right away.

Thanks a lot for the solid work!

brillout commented 3 weeks ago

I'm glad it works out for you!

Definitely let us know if you hit any issues; there is room for improvement which we will be implementing upon user feedback.