When using the useLogo hook provided by theme-classic in a custom page, the associated attributes do not update following a chance between dark/light themes.
:+1:
import React from 'react';
import Layout from '@theme/Layout';
import useLogo from '@theme/hooks/useLogo';
function LogoTest() {
const {logoImageUrl} = useLogo();
return (
<Layout title="LogoTest">
<img src={logoImageUrl} />
</Layout>
);
}
export default LogoTest;
Ensure both navbar.logo.src and navbar.logo.srcDark are set in the config.
Build + load in browser.
Toggle theme light/dark state.
src attribute should change between src and srcDark values.
src remains on original value.
See above.
We have not documented this hook, so it is not intended to be used by end-users.
But if you want this hook to work, you need to use state of isClient, as shown below.
Awesome. Thanks for looking into this.
After putting that into the test case unfortunately the behavior is the same.
import React from 'react';
import Layout from '@theme/Layout';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useLogo from '@theme/hooks/useLogo';
function LogoTest() {
const {isClient} = useDocusaurusContext();
const {logoImageUrl} = useLogo();
return (
<Layout title="LogoTest">
<img key={isClient} src={logoImageUrl} />
</Layout>
);
}
export default LogoTest;
Indeed it is, even useThemeContext does not work in pages.
@yangshun any ideas on this?
I'm still building up my mental model of this project, but in case it's of relevance pulling isDarkTheme directly from useTheme does work, but only on initial page load.
After some investigation, I found the reason.
First, you should not use useTheme(). It's designed to be used internally by useThemeContext(). You should use useThemeContext() instead. useLogo is fine since it calls useThemeContext() under the hood.
useThemeContext(), as the name implies, must work under some context. The context is <ThemeProvider>, which is part of Layout. See https://github.com/facebook/docusaurus/blob/d391a2bcdbe7d5096d08be88d8bf5467e70264a8/packages/docusaurus-theme-classic/src/theme/Layout/index.js#L52.
In a page, you might have something like
import React from 'react';
import Layout from '@theme/Layout';
function Page() {
return (
<Layout title="Foo" description="bar">
Baz
</Layout>
);
}
export default Page;
If you try to useLogo, it might become:
import React from 'react';
import Layout from '@theme/Layout';
function Page() {
// oops, use the ThemeProvider without being its child.
const logo = useLogo();
return (
<Layout title="Foo" description="bar">
Baz
</Layout>
);
}
export default Page;
A workaround is to move the content of the page to another component:
import React from 'react';
import Layout from '@theme/Layout';
function Content() {
const logo = useLogo();
return logo;
}
function Page() {
return (
<Layout title="Foo" description="bar">
<Content />
</Layout>
);
}
export default Page;
Since we removed the useLogo hook (see #3730), this issue is no longer relevant, so I'm closing it.