Creating custom hook to set cookies, measure component size with ref, scroll freeze on component, get window width.

This commit is contained in:
Bradley Shellnut 2021-09-24 14:56:48 -07:00
parent 05fe1d93e7
commit 5cab62fd7e
13 changed files with 211 additions and 66 deletions

View file

@ -5,6 +5,9 @@ import Toggle from './components/Toggle';
import Inc from './components/Inc';
import Mount from './components/Mount';
import Hover from './components/Hover';
import Cookie from "./components/Cookie";
import { PageWrapper } from "./state";
import Nav from "./components/Nav";
import Menu from "./Menu";
import blue from "./blue.png";
import purp from "./purp.png";
@ -13,16 +16,19 @@ import green from "./green.png";
function App() {
return (
<PageWrapper>
<div>
<Header>
<Menu />
<h1>Header</h1>
</Header>
<Nav />
<Container>
<h2>Super Cool</h2>
<Toggle />
<Inc />
<Mount />
<Cookie />
<Hover />
<CardGrid>
@ -45,6 +51,7 @@ function App() {
</CardGrid>
</Container>
</div>
</PageWrapper>
);
}

View file

@ -1,6 +1,10 @@
import React from "react";
import { useAppState } from "./state";
const Menu = () => (
const Menu = () => {
const { toggleMenu } = useAppState();
return (
<button onClick={toggleMenu}>
<svg viewBox="0 0 18 15" width="20">
<path
fill="#fff"
@ -15,6 +19,7 @@ const Menu = () => (
d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"
/>
</svg>
);
</button>
)};
export default Menu;

22
src/components/Cookie.js Normal file
View file

@ -0,0 +1,22 @@
import { useCookies } from "../hooks";
const Cookie = () => {
const [ cookie, setCookie ] = useCookies({ key: "tester" });
return (
<div>
<h1>{cookie || ''}</h1>
<input type="text" value={cookie} onChange={(e) => setCookie(e.target.value)} />
</div>
)
}
export default Cookie;
// Different types of api
// const { value, get, set } = useCookie({key, value})
// value
// const { value, get, set } = useCookie({key: anotherKey, value})
// const { get, set } = useCookie()
// get("theme")

View file

@ -1,15 +1,23 @@
import React from 'react';
import { Card } from '../Elements';
import black from "../black.png"
import { useHover } from '../hooks';
import { useHover, useWindowWidth, useMeasure } from '../hooks';
export const Hover = () => {
const [ isHovered, bind ] = useHover();
console.log('isHovered', isHovered);
const width = useWindowWidth();
const [{ref}, bounds] = useMeasure();
console.log('bounds', bounds);
if (width < 500) return null;
return (
<div>
<Card {...bind} style={{ background: isHovered ? "var(--purp)" : "var(--black)" }}>
<Card
ref={ref}
{...bind}
style={{ background: isHovered ? "var(--purp)" : "var(--black)" }}
>
<h3>Some card</h3>
<img src={black} />
</Card>

30
src/components/Nav.js Normal file
View file

@ -0,0 +1,30 @@
import { useAppState } from "../state";
import { useScrollFreeze } from "../hooks";
const NavWrapper = () => {
const { isMenuOpen } = useAppState();
if (!isMenuOpen) return null;
return <Nav />
}
export const Nav = () => {
const { toggleMenu } = useAppState();
useScrollFreeze ();
return (
<nav style={{
background: 'var(--black)',
color: 'white',
position: 'fixed',
width: '100vw',
height: '100vh',
left: 0,
right: 0
}}>
<h1>Hello</h1>
<button onClick={toggleMenu}>Close</button>
</nav>
)
}
export default NavWrapper;

View file

@ -1,14 +0,0 @@
import React, { createConext, useState } from 'react';
import { useToggle } from '../hooks';
const AppContext = createConext({
isMenuOpen: false,
});
const PageWrapper = ({children}) => {
const {isToggled, toggle} = useToggle();
return <AppContext.Provider
value={{ isMenuOpen: false}}>
{children}
</AppContext.Provider>
};

View file

@ -1,4 +1,8 @@
export * from './useCookie';
export * from './useHover';
export * from './useInc';
export * from './useMeasure';
export * from './useMount';
export * from './useScrollFreeze';
export * from './useToggle';
export * from './useWindowWidth';

13
src/hooks/useCookie.js Normal file
View file

@ -0,0 +1,13 @@
import { useState, useEffect } from 'react';
import Cookies from 'js-cookie';
export const useCookies = ({ key }) => {
const initial = Cookies.get(key);
const [ cookie, setStateCookie ] = useState(initial);
useEffect(() => {
Cookies.set(key, cookie)
}, [cookie, key]);
return [ cookie, setStateCookie ];
};

23
src/hooks/useMeasure.js Normal file
View file

@ -0,0 +1,23 @@
import { useState, useRef, useEffect } from 'react';
export const useMeasure = () => {
const ref = useRef();
const [bounds, setBounds] = useState({ left: 0, top: 0, width: 0, height: 0 });
const [ resizeO ] = useState(() => {
return new ResizeObserver(([entry]) => setBounds(entry.contentRect))
});
useEffect(() => {
if (ref.current) {
resizeO.observe(ref.current);
}
return () => {
return resizeO.disconnect();
};
}, [resizeO]);
return [{ ref }, bounds];
}

View file

@ -0,0 +1,12 @@
import { useLayoutEffect } from 'react';
export const useScrollFreeze = () => {
useLayoutEffect(() => {
const original = window.getComputedStyle(document.body).overflow;
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = original;
};
}, [])
};

View file

@ -0,0 +1,17 @@
import { useState, useEffect } from "react";
export const useWindowWidth = () => {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => {
setWidth(window.innerWidth);
}
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
});
return width;
}

17
src/state/PageWrapper.js Normal file
View file

@ -0,0 +1,17 @@
import { createContext, useContext } from 'react';
import { useToggle } from '../hooks';
export const AppContext = createContext({
isMenuOpen: false,
});
export const PageWrapper = ({children}) => {
const { isToggled, toggle } = useToggle(false);
return (
<AppContext.Provider value={{ isMenuOpen: isToggled, toggleMenu: toggle }}>
{children}
</AppContext.Provider>
);
};
export const useAppState = () => useContext(AppContext);

1
src/state/index.js Normal file
View file

@ -0,0 +1 @@
export * from './PageWrapper';