Edit this page

useConfig()

Environment: server, client.

Provided by: vike-react/vike-vue/vike-solid.

You need vike-react/vike-vue/vike-solid to be able to use useConfig().

The useConfig() hook enables you to define these settings inside Vike hooks and UI components.

See also: Guides > <head> tags.

Vike hooks

You can use useConfig() inside any Vike hook, most notably +data.

// pages/movies/+data.jsx
 
import { useConfig } from 'vike-react/useConfig' // or vike-{vue,solid}
 
export async function data(pageContext) {
  const config = useConfig()
 
  const response = await fetch('https://star-wars.brillout.com/api/films.json')
  let { movies } = await response.json()
 
  config({
    title: `${movies.length} Star Wars Movies`
    Head: <meta name="description" content={`List of all ${movies.length} Star Wars movies.`} />
  })
 
  return { movies }
}

Make sure to call useConfig() before any await:

export async function data(pageContext) {
  const response = await fetch('https://star-wars.brillout.com/api/films.json')
  // ❌ Doesn't work: useConfig() has to be called before `await fetch()`
  const config = useConfig()
}

Normally hooks can only be used inside UI components — useConfig() is different: it can also be used inside Vike hooks. We call it a universal hook (useConfig() is the only universal hook so far).

UI components

You can also use useConfig() inside UI components.

// pages/product/@id/+Page.jsx
 
import { useConfig } from 'vike-react/useConfig' // or vike-{vue,solid}
import { useData } from 'vike-react/useData' // or vike-{vue,solid}
 
export function Page() {
  const config = useConfig()
  const data = useData()
 
  // Set <head> tags
  config({
    title: data.product.name,
    // Image shown when sharing on social sites (Twitter, WhatsApp, ...)
    Head: <meta property="og:image" content={data.product.image} />
  })
 
  // Render UI
  return <>
    <h1>{data.product.name}</h1>
    <p>{data.product.description}</p>
  </>
}

For Vue you can use the following:

import { h } from 'vue'
config({
  Head: h('meta', {
    property: 'og:image',
    content: data.product.image
  })
})

See also: API > useData().

<Config> & <Head>

For a more declarative usage, you can use <Config> and <Head> instead of useConfig():

// pages/product/@id/+Page.jsx
 
import { Config } from 'vike-react/Config' // or vike-{vue,solid}
import { Head } from 'vike-react/Head' // or vike-{vue,solid}
 
export function Page() {
  const data = useData()
 
  // Render UI and <head> tags
  return <>
    <Config title={data.product.name} />
    <Head>
      {/* Image shown when sharing on social sites (Twitter, WhatsApp, ...) */}
      <meta property="og:image" content={data.product.image}>
    </Head>
    <h1>{data.product.name}</h1>
    <p>{data.product.description}</p>
  </>
}

The <Config> and <Head> components are only useConfig() wrappers and achieve the same result — they are just for convenience.

For example, the following are equivalent:

export function Page() {
  const data = useData()
  const config = useConfig() 
 
  config({ 
    title: data.product.name, 
    Head: <meta property="og:image" content={data.product.image} /> 
  }) 
 
  return (
    <Config title={data.product.name} /> 
    <Head>
      <meta property="og:image" content={data.product.image} />
    </Head>
    {/* ... */}
  )
}

Likewise, <Head><something/></Head> and <Config Head={<something/>}/> are equivalent as well.

Unlike other frameworks, Vike doesn't implement a <Title> component because its value must be a string — <Title><b>Hello</b> World</Title> doesn't make sense.

Example: React Query

The useConfig() hook is especially useful when using extensions such as vike-react-query and vike-react-apollo that enable components to fetch data. It enables your components to use the data they fetch to set <head> tags.

import { useConfig } from 'vike-react/useConfig'
import { useSuspenseQuery } from '@tanstack/react-query'
 
function Movies() {
  // Fetch data
  const query = useSuspenseQuery({
    queryKey: ['movies'],
    queryFn: () => fetch('https://star-wars.brillout.com/api/films.json')
  })
  const movies = query.data
 
  // Set <head> tags
  const config = useConfig()
  config({
    title: `${movies.length} Star Wars Movies` // <title>
    Head: <meta name="description" content={`List of all ${movies.length} Star Wars movies.`} />
  })
 
  // Render UI
  return (
    <ul>{
      movies.map(({ title }) => (
        <li>{title}</li>
      ))
    }</ul>
  )
}

The <meta name="description"> tag is only shown to bots. See the explanation in the section below HTML Streaming.

Or with <Config> and <Head>:

import { Config } from 'vike-react/Config'
import { Head } from 'vike-react/Head'
import { useSuspenseQuery } from '@tanstack/react-query'
 
function Movies() {
  // Fetch data
  const query = useSuspenseQuery({
    queryKey: ['movies'],
    queryFn: () => fetch('https://star-wars.brillout.com/api/films.json')
  })
  const movies = query.data
 
  // Render UI and <head> tags
  return (
    <Config title={`${movies.length} Star Wars Movies`} />
    <Head>
      <meta name="description" content={`List of all ${movies.length} Star Wars movies.`} />
    </Head>
    <ul>{
      movies.map(({ title }) => (
        <li>{title}</li>
      ))
    }</ul>
  )
}

HTML Streaming

If you use HTML Streaming together with useConfig() inside UI components, some <head> tags may be missing from the streamed HTML.

This happens when a component calls useConfig() after the HTML stream has already started and the whole <head> block has already been sent to the client — it's too late to inject additional <head> tags.

This might seem like an issue, but it actually isn't. See the explanation below.

Bots

If you use vike-react then note that it uses react-streaming which automatically disables HTML Streaming for crawlers (e.g. Googlebot), ensuring crawlers always get all <head> tags. See react-streaming Docs > Bots.

You can use $ curl to see the HTML response that bots and crawlers receive:

# What bots and crawls get: no HTML Streaming, just "classic SSR"
$ curl http://localhost:3000/movies
# What human users get: HTML Streaming
$ curl http://localhost:3000/movies -N -H "User-Agent: chrome"

Consequently, <head> tags intended for bots (SEO, PWA settings, ...) are guaranteed to be included in the HTML. They might be missing for human users, but that isn't an issue.

+title

If <Config title={'some-title'}> runs after the <head> block has already been sent, the HTML snippet <script>document.title = 'some-title'</script> is injected to dynamically update the page title.

Currently, +title is the only setting that uses such mechanism.

Consequently, the <title> tag is guaranteed to be included in the HTML for bots (see section above), while human users see an up-to-date page title.

See also

OSZAR »