mirror of
https://github.com/BradNut/react-hooks-library
synced 2025-09-08 17:40:20 +00:00
Added local storage, script, and theme hooks.
This commit is contained in:
parent
5cab62fd7e
commit
43a73aae8a
12 changed files with 157 additions and 7 deletions
|
|
@ -4,4 +4,6 @@
|
|||
--blue: #4f8cdd;
|
||||
--black: #3b2c41;
|
||||
--green: #a3ffc1;
|
||||
--bg: #fff;
|
||||
--text: #333;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import Inc from './components/Inc';
|
|||
import Mount from './components/Mount';
|
||||
import Hover from './components/Hover';
|
||||
import Cookie from "./components/Cookie";
|
||||
import Script from './components/Script';
|
||||
import Local from './components/Local';
|
||||
import Theme from './components/Theme';
|
||||
import { PageWrapper } from "./state";
|
||||
import Nav from "./components/Nav";
|
||||
import Menu from "./Menu";
|
||||
|
|
@ -25,10 +28,13 @@ function App() {
|
|||
<Nav />
|
||||
<Container>
|
||||
<h2>Super Cool</h2>
|
||||
<Theme />
|
||||
<Script />
|
||||
<Toggle />
|
||||
<Inc />
|
||||
<Mount />
|
||||
<Cookie />
|
||||
<Local />
|
||||
<Hover />
|
||||
|
||||
<CardGrid>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export const Container = styled.div`
|
|||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 60px;
|
||||
color: var(--text);
|
||||
`;
|
||||
|
||||
export const CardGrid = styled.div`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import React from 'react';
|
||||
import { Card } from '../Elements';
|
||||
import black from "../black.png"
|
||||
import { useHover, useWindowWidth, useMeasure } from '../hooks';
|
||||
|
|
@ -6,15 +5,15 @@ import { useHover, useWindowWidth, useMeasure } from '../hooks';
|
|||
export const Hover = () => {
|
||||
const [ isHovered, bind ] = useHover();
|
||||
const width = useWindowWidth();
|
||||
const [{ref}, bounds] = useMeasure();
|
||||
console.log('bounds', bounds);
|
||||
// const [{ref}, bounds] = useMeasure();
|
||||
// console.log('bounds', bounds);
|
||||
|
||||
if (width < 500) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card
|
||||
ref={ref}
|
||||
// ref={ref}
|
||||
{...bind}
|
||||
style={{ background: isHovered ? "var(--purp)" : "var(--black)" }}
|
||||
>
|
||||
|
|
|
|||
14
src/components/Local.js
Normal file
14
src/components/Local.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { useLocalStorage } from "../hooks";
|
||||
|
||||
const Local = () => {
|
||||
const [ value, setValue ] = useLocalStorage("tester", "I am initial");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{value || ''}</h1>
|
||||
<input type="text" value={value} onChange={(e) => setValue(e.target.value)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Local;
|
||||
15
src/components/Script.js
Normal file
15
src/components/Script.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { useScript } from "../hooks"
|
||||
|
||||
const Script = () => {
|
||||
const [ isLoaded, isError ] = useScript('https://www.google.com/recaptcha/api.js');
|
||||
console.log('isLoaded, isError', isLoaded, isError);
|
||||
if (!isLoaded) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Script</h3>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Script;
|
||||
16
src/components/Theme.js
Normal file
16
src/components/Theme.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { useTheme } from "../hooks";
|
||||
|
||||
const Theme = () => {
|
||||
const [theme, setTheme] = useTheme();
|
||||
return (
|
||||
<div>
|
||||
<select name="" id="" defaultValue={theme}
|
||||
onChange={(e) => setTheme(e.target.value)}>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Theme;
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
export * from './useCookie';
|
||||
export * from './useHover';
|
||||
export * from './useInc';
|
||||
export * from './useLocalStorage';
|
||||
export * from './useMeasure';
|
||||
export * from './useMount';
|
||||
export * from './useScrollFreeze';
|
||||
export * from './useScript';
|
||||
export * from './useTheme';
|
||||
export * from './useToggle';
|
||||
export * from './useWindowWidth';
|
||||
|
|
|
|||
12
src/hooks/useLocalStorage.js
Normal file
12
src/hooks/useLocalStorage.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
|
||||
export const useLocalStorage = (key, initial) => {
|
||||
const item = window.localStorage.getItem(key);
|
||||
const [ value, setValue ] = useState(item || initial);
|
||||
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem(key, value);
|
||||
}, [value, key, initial]);
|
||||
|
||||
return [ value, setValue ];
|
||||
};
|
||||
59
src/hooks/useScript.js
Normal file
59
src/hooks/useScript.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
|
||||
let cached = [];
|
||||
|
||||
export const useScript = (src) => {
|
||||
const [ status, setStatus ] = useState({
|
||||
loaded: false,
|
||||
error: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (cached.includes(src)) {
|
||||
setStatus({
|
||||
loaded: true,
|
||||
error: false,
|
||||
});
|
||||
} else {
|
||||
cached.push(src);
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.async = true;
|
||||
|
||||
const onLoad = () => {
|
||||
setStatus({
|
||||
loaded: true,
|
||||
error: false,
|
||||
});
|
||||
}
|
||||
|
||||
const onError = () => {
|
||||
const i = cached.indexOf(src);
|
||||
if (i >= 0) {
|
||||
cached.splice(i, 1);
|
||||
}
|
||||
// cached = cached.filter(item => item !== src);
|
||||
|
||||
script.remove();
|
||||
|
||||
setStatus({
|
||||
loaded: true,
|
||||
error: true,
|
||||
});
|
||||
}
|
||||
|
||||
script.addEventListener('load', onLoad);
|
||||
script.addEventListener('error', onError);
|
||||
|
||||
document.body.appendChild(script);
|
||||
|
||||
return () => {
|
||||
script.removeEventListener('load', onLoad);
|
||||
script.removeEventListener('error', onError);
|
||||
}
|
||||
}
|
||||
}, [src]);
|
||||
|
||||
return [ status.loaded, status.error ];
|
||||
}
|
||||
14
src/hooks/useTheme.js
Normal file
14
src/hooks/useTheme.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { useEffect } from 'react';
|
||||
import { useLocalStorage } from './useLocalStorage';
|
||||
|
||||
export const useTheme = () => {
|
||||
const [theme, setTheme] = useLocalStorage('theme', 'light');
|
||||
|
||||
useEffect(() => {
|
||||
// Removing all class names on body before setting, could keep and only remove what we want
|
||||
document.body.className = "";
|
||||
document.body.classList.add(theme);
|
||||
}, [theme]);
|
||||
|
||||
return [theme, setTheme];
|
||||
}
|
||||
|
|
@ -1,13 +1,22 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
body.dark {
|
||||
--bg: #333;
|
||||
--text: #fff;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue