-
Leveraging react context for global state to store cms data like strings and urls. This way I can inject these strings directly into components without passing props all over the place.
-
the cms context :
interface CmsData {
homePageContent?: HomePageContent;
aboutPageContent?: AboutPageContent
}
type ContextInterface = [
cmsData: CmsData | undefined,
setMessages: React.Dispatch<React.SetStateAction<CmsData | undefined>>
];
const CmsContext = React.createContext({} as ContextInterface);
export const CmsProvider: React.FC = ({ children }) => {
const [cmsContent, setCmsContent] = useState<CmsData | undefined>(undefined);
return (
<CmsContext.Provider value={[cmsContent, setCmsContent]}>
{children}
</CmsContext.Provider>
);
};
using useContext
we can make hook to set and get the cms data:
export function useCmsContent(content?: CmsData) {
const [cmsContent, setMessagesState] = useContext(CmsContext);
useEffect(() => {
if (!content) {
return;
}
setMessagesState(content);
});
return cmsContent;
}
with this in place, can set data on first page load…
const Home: React.FC<HomeProps> = ({ homePageContent }) => {
// homePageContent is data from next getStaticProps
useCmsContent({ homePageContent });
return (
<>
{/*...truncated for brevity... */}
</>
)
}
then in any children components we can use the data easily without having messy props all over the place:
const DeeplyNestedComponent: React.FC = () => {
const cmsData = useCmsContent();
return (
<>
{cmsData.homepageData.someText}
</>
)
}