Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/common/utils/__tests__/clientOnly.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { useHydrated } from '../clientOnly';

describe('useHydrated hook', () => {
it('should return true after hydration', async () => {
let renderedHydratedValue: boolean;

const TestComponent = () => {
const hydrated = useHydrated();
renderedHydratedValue = hydrated;
return null;
};

render(<TestComponent />);

await waitFor(() => {
expect(renderedHydratedValue).toBe(true);
});
});
});
4 changes: 1 addition & 3 deletions src/common/utils/clientOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let hydrating = true;
* );
* ```
*/
const useHydrated = () => {
export const useHydrated = () => {
let [hydrated, setHydrated] = useState(() => !hydrating);

useEffect(function hydrate() {
Expand All @@ -29,5 +29,3 @@ const useHydrated = () => {

return hydrated;
};

export { useHydrated };
35 changes: 35 additions & 0 deletions stories/Utils/Documentation-server.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meta, Story, Canvas, Props } from '@storybook/addon-docs';

<Meta
title="DCXLibrary/Utils/useHydrated"
parameters={{
viewMode: 'docs',
previewTabs: {
canvas: { hidden: true },
},
}}
/>

# `useHydrated` utility

This hook lets you detect if your component is already hydrated. This means the JS for the element loaded client-side and React is running.
useHydrated ensure the components are SSR(Server Side Rendering)-friendly, you can render different things on the server and client while ensuring the hydration will not have a mismatched HTML.

## Example

```js
import { useHydrated } from '@capgeminiuk/dcx-react-library';

export function Component() {
let isHydrated = useHydrated();

if (isHydrated) {
return <ClientOnlyComponent />;
}

return <ServerFallback />;
}
```

When doing SSR, the value of isHydrated will always be false. The first client-side render isHydrated will still be false, and then it will change to true.
After the first client-side render, future components rendered calling this hook will receive true as the value of isHydrated. This way, your server fallback UI will never be rendered on a route transition.