如何检测文档中是否存在另一个组件?
How to detect if another component is present in the document?
我有一个用 React Static 构建的站点,它有一个始终存在的页眉组件。根据当前页面是否有 hero 组件,Header 应该是浅色或深色。
Header 在路由之外呈现,useEffect
在子对象呈现之前触发。这是可能因为路由的原因
这是当前代码:
// App.js
import React, { useState, useEffect } from 'react'
import { Root, Routes } from 'react-static'
export default () => {
const [useDarkTheme, setUseDarkTheme] = useState(false);
useEffect(() => {
if (typeof document !== "undefined") {
const heroPresent = document.querySelectorAll(".o-hero").length > 0;
console.log("The hero is present: " + heroPresent);
setUseDarkTheme(!heroPresent);
}
})
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<Header useDarkTheme={ useDarkTheme } />
<Routes default />
</React.Suspense>
</Root>
);
}
<Routes default />
渲染的是React Staticstatic.config.js
配置的静态页面。
下面是 Hero 组件的示例:
// Hero.js
import React from "react";
export default () => {
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
当我 运行 应用程序并查看日志时,这是我得到的:
The hero is present: false
This is the Hero rendering. If this exist, the Header should be dark.
尽管 Hero 在路由器中而 Header 不在,但我怎么能以某种方式从 Header 中检测到 Hero 的存在?这感觉像是一个很常见的用例,但我在互联网上找不到任何信息。
提前致谢!
所以我最终使用 useContext
为所有 children 提供 getter 和 setter Header 的主题(深色或光)。该解决方案的灵感来自 this answer。解决方案如下所示:
// App.js
import React, { useState, useContext } from 'react'
import { Root, Routes } from 'react-static'
import { HeaderThemeContext } from "./context";
export default () => {
const { theme } = useContext(HeaderThemeContext);
const [headerTheme, setHeaderTheme] = useState(theme);
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<HeaderThemeContext.Provider value={ { theme: headerTheme, setTheme: setHeaderTheme } }>
<Header theme={ headerTheme } />
<Routes default />
</HeaderThemeContext.Provider>
</React.Suspense>
</Root>
);
}
// Hero.js
import React from "react";
import { headerThemes, setHeaderTheme } from "./context";
export default () => {
setHeaderTheme(headerThemes.DARK);
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
// context.js
import React, { createContext, useContext } from "react";
export const headerThemes = {
LIGHT: "light",
DARK: "dark",
};
export const HeaderThemeContext = createContext({
theme: headerThemes.LIGHT,
setTheme: () => {}
});
// This is a hook and can only be used in a functional component with access to the HeaderThemeContext.
export const setHeaderTheme = theme => useContext(HeaderThemeContext).setTheme(theme);
这提供了全局访问权限来设置和获取 header 主题,这可能不是可选的,但它现在可以使用,我认为它很好。如果有更好的方法,请告诉我。
我有一个用 React Static 构建的站点,它有一个始终存在的页眉组件。根据当前页面是否有 hero 组件,Header 应该是浅色或深色。
Header 在路由之外呈现,useEffect
在子对象呈现之前触发。这是可能因为路由的原因
这是当前代码:
// App.js
import React, { useState, useEffect } from 'react'
import { Root, Routes } from 'react-static'
export default () => {
const [useDarkTheme, setUseDarkTheme] = useState(false);
useEffect(() => {
if (typeof document !== "undefined") {
const heroPresent = document.querySelectorAll(".o-hero").length > 0;
console.log("The hero is present: " + heroPresent);
setUseDarkTheme(!heroPresent);
}
})
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<Header useDarkTheme={ useDarkTheme } />
<Routes default />
</React.Suspense>
</Root>
);
}
<Routes default />
渲染的是React Staticstatic.config.js
配置的静态页面。
下面是 Hero 组件的示例:
// Hero.js
import React from "react";
export default () => {
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
当我 运行 应用程序并查看日志时,这是我得到的:
The hero is present: false
This is the Hero rendering. If this exist, the Header should be dark.
尽管 Hero 在路由器中而 Header 不在,但我怎么能以某种方式从 Header 中检测到 Hero 的存在?这感觉像是一个很常见的用例,但我在互联网上找不到任何信息。
提前致谢!
所以我最终使用 useContext
为所有 children 提供 getter 和 setter Header 的主题(深色或光)。该解决方案的灵感来自 this answer。解决方案如下所示:
// App.js
import React, { useState, useContext } from 'react'
import { Root, Routes } from 'react-static'
import { HeaderThemeContext } from "./context";
export default () => {
const { theme } = useContext(HeaderThemeContext);
const [headerTheme, setHeaderTheme] = useState(theme);
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<HeaderThemeContext.Provider value={ { theme: headerTheme, setTheme: setHeaderTheme } }>
<Header theme={ headerTheme } />
<Routes default />
</HeaderThemeContext.Provider>
</React.Suspense>
</Root>
);
}
// Hero.js
import React from "react";
import { headerThemes, setHeaderTheme } from "./context";
export default () => {
setHeaderTheme(headerThemes.DARK);
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
// context.js
import React, { createContext, useContext } from "react";
export const headerThemes = {
LIGHT: "light",
DARK: "dark",
};
export const HeaderThemeContext = createContext({
theme: headerThemes.LIGHT,
setTheme: () => {}
});
// This is a hook and can only be used in a functional component with access to the HeaderThemeContext.
export const setHeaderTheme = theme => useContext(HeaderThemeContext).setTheme(theme);
这提供了全局访问权限来设置和获取 header 主题,这可能不是可选的,但它现在可以使用,我认为它很好。如果有更好的方法,请告诉我。