76 lines
1.7 KiB
Markdown
76 lines
1.7 KiB
Markdown
---
|
|
tags:
|
|
- javascript
|
|
- react
|
|
---
|
|
|
|
# Custom hook examples
|
|
|
|
## Determine viewport width
|
|
|
|
### Hook
|
|
|
|
```js
|
|
// useViewportWidth.js
|
|
import { useEffect, useState } from "react";
|
|
|
|
export default function (viewportWidth) {
|
|
const [matchesViewportWidth, setMatchesViewportWidth] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const handleResize = () =>
|
|
window.innerWidth < viewportWidth
|
|
? setMatchesViewportWidth(true)
|
|
: setMatchesViewportWidth(false);
|
|
|
|
window.addEventListener("resize", handleResize);
|
|
|
|
// Call on initialization to determine initial width
|
|
handleResize();
|
|
|
|
// Clean-up listener to prevent memory leaks
|
|
return () => window.removeEventListener("resize", handleResize);
|
|
}, [viewportWidth]);
|
|
|
|
return matchesViewportWidth;
|
|
}
|
|
```
|
|
|
|
### Unit test
|
|
|
|
```js
|
|
import useViewportWidth from "./useViewportWidth";
|
|
import { fireEvent } from "@testing-library/react";
|
|
import { act } from "react-dom/test-utils";
|
|
import { renderHook } from "@testing-library/react-hooks";
|
|
|
|
describe("useViewportWidth", () => {
|
|
it("returns `true` when window resized to mobile viewport width", () => {
|
|
// Arrange
|
|
const { result } = renderHook(() => useViewportWidth(768));
|
|
|
|
// Act
|
|
act(() => {
|
|
window.innerWidth = 500;
|
|
fireEvent(window, new Event("resize"));
|
|
});
|
|
|
|
// Assert
|
|
expect(result.current).toBe(true);
|
|
});
|
|
|
|
it("returns `false` when window resized to width greater than mobile viewport", () => {
|
|
// Arrange
|
|
const { result } = renderHook(() => useViewportWidth(768));
|
|
|
|
// Act
|
|
act(() => {
|
|
window.innerWidth = 1058;
|
|
fireEvent(window, new Event("resize"));
|
|
});
|
|
|
|
// Assert
|
|
expect(result.current).toBe(false);
|
|
});
|
|
})``;
|
|
```
|