├── CustomHooks ├── useAxios.js ├── useDarkMode.js ├── useForm.js ├── useLocalStorage.js └── useMusicPlayer.js ├── LICENSE └── README.md /CustomHooks/useAxios.js: -------------------------------------------------------------------------------- 1 | //This hook works together with useLocalStorage hook and axios for data fetching 2 | 3 | import axios from 'axios'; 4 | import { useEffect } from 'react' 5 | 6 | import useLocalStorage from './useLocalStorage'; 7 | 8 | const useAxios = (url) => { 9 | const [data, setData] = useLocalStorage('data', []) 10 | useEffect(() => { 11 | axios.get(url) 12 | .then(response => setData(response.data)) 13 | .catch(error => console.log('Error: Axios: ', error)) 14 | }, [url]) 15 | return [data]; 16 | } 17 | export default useAxios; 18 | -------------------------------------------------------------------------------- /CustomHooks/useDarkMode.js: -------------------------------------------------------------------------------- 1 | // This hook works together with useLocalStorage hook 2 | 3 | import { useLocalStorage } from "./useLocalStorage"; 4 | import { useEffect } from "react"; 5 | 6 | export const useDarkMode = (key, initialValues) => { 7 | const [darkMode, setDarkMode] = useLocalStorage(key, initialValues); 8 | 9 | useEffect(()=> { 10 | if (darkMode === true ) { 11 | document.body.classList.add("dark-mode"); 12 | } else { 13 | document.body.classList.remove("dark-mode") 14 | } 15 | }, [darkMode]); 16 | 17 | return [darkMode, setDarkMode] 18 | } 19 | 20 | // Below is a Navbar component example to use this hook 21 | 22 | import React from 'react'; 23 | import { useDarkMode } from "../hooks/useDarkMode"; 24 | 25 | const Navbar = () => { 26 | const [darkMode, setDarkMode] = useDarkMode("darkMode",false); 27 | const toggleMode = e => { 28 | e.preventDefault(); 29 | setDarkMode(!darkMode); 30 | }; 31 | return ( 32 | 41 | ); 42 | }; 43 | export default Navbar; 44 | 45 | // Below is the CSS relating to this hook 46 | .navbar { 47 | align-items: center; 48 | border-bottom: 1px solid rgb(221, 221, 221); 49 | display: flex; 50 | height: 70px; 51 | justify-content: space-between; 52 | padding: 0 3%; 53 | margin: 0 auto; 54 | width: 92%; 55 | -webkit-box-shadow: 0px 2px 15px -8px rgba(0, 0, 0, 0.42); 56 | -moz-box-shadow: 0px 2px 15px -8px rgba(0, 0, 0, 0.42); 57 | box-shadow: 0px 2px 15px -8px rgba(0, 0, 0, 0.42); 58 | } 59 | 60 | .dark-mode { 61 | color: #fff; 62 | background-color: #313843; 63 | 64 | .navbar { 65 | background-color: #1F2022; 66 | border: none; 67 | } 68 | } 69 | 70 | .dark-mode__toggle { 71 | background: papayawhip; 72 | border-radius: 50px; 73 | border: 1px solid black; 74 | height: 20px; 75 | position: relative; 76 | width: 40px; 77 | } 78 | 79 | .toggle { 80 | background: #f68819; 81 | border-radius: 50px; 82 | height: 20px; 83 | left: 0; 84 | position: absolute; 85 | transition: 0.2s; 86 | width: 20px; 87 | } 88 | 89 | .toggled { 90 | left: 18px; 91 | } 92 | -------------------------------------------------------------------------------- /CustomHooks/useForm.js: -------------------------------------------------------------------------------- 1 | // This hook works together with useLocalStorage hook 2 | 3 | import { useLocalStorage } from "./useLocalStorage"; 4 | 5 | export const useForm = (key, initialValues, callback) => { 6 | const [values, setValues] = useLocalStorage(key, initialValues); 7 | 8 | const handleChanges = e => { 9 | setValues({ ...values, [e.target.name]: e.target.value }); 10 | }; 11 | 12 | const handleSubmit = e => { 13 | e.preventDefault(); 14 | callback(); 15 | }; 16 | 17 | return [values, handleChanges, handleSubmit]; 18 | }; 19 | -------------------------------------------------------------------------------- /CustomHooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export const useLocalStorage = (key, initialValue) => { 4 | const [storedValue, setStoredValue] = useState(()=> { 5 | const item = window.localStorage.getItem(key); 6 | return item ? JSON.parse(item) : initialValue; 7 | }); 8 | 9 | const setValue = value => { 10 | window.localStorage.setItem(key, JSON.stringify(value)); 11 | setStoredValue(value); 12 | } 13 | 14 | return [storedValue, setValue]; 15 | } -------------------------------------------------------------------------------- /CustomHooks/useMusicPlayer.js: -------------------------------------------------------------------------------- 1 | // This hook uses React Context API, line 4 and line 7 can be changed to any name and path 2 | // below is the initial state object 3 | // const [state, setState] = useState({ 4 | // audioPlayer: new Audio(), 5 | // tracks: [], 6 | // currentTrackIndex: null, 7 | // isPlaying: false 8 | // }); 9 | 10 | import { useContext } from 'react'; 11 | import { MusicContext } from '../contexts/MusicContext'; 12 | 13 | const useMusicPlayer = () => { 14 | const [state, setState] = useContext(MusicContext); 15 | 16 | function playTrack(index) { 17 | if (index === state.currentTrackIndex) { 18 | togglePlay(); 19 | } else { 20 | state.audioPlayer.pause(); 21 | state.audioPlayer = new Audio(state.tracks[index].file); 22 | state.audioPlayer.play(); 23 | setState({ ...state, currentTrackIndex: index, isPlaying: true }); 24 | } 25 | } 26 | 27 | function togglePlay() { 28 | if (state.isPlaying) { 29 | state.audioPlayer.pause(); 30 | } else { 31 | state.audioPlayer.play(); 32 | } 33 | 34 | setState({ ...state, isPlaying: !state.isPlaying }); 35 | } 36 | 37 | function playPreviousTrack() { 38 | let newTrackIndex = 39 | state.currentTrackIndex === 0 40 | ? state.tracks.length - 1 41 | : state.currentTrackIndex - 1; 42 | playTrack(newTrackIndex); 43 | } 44 | 45 | function playNextTrack() { 46 | let newTrackIndex = 47 | state.currentTrackIndex === state.tracks.length - 1 48 | ? 0 49 | : state.currentTrackIndex + 1; 50 | playTrack(newTrackIndex); 51 | } 52 | 53 | return { 54 | playTrack, 55 | togglePlay, 56 | currentTrackIndex: state.currentTrackIndex, 57 | currentTrackName: 58 | state.tracks[state.currentTrackIndex] && 59 | state.tracks[state.currentTrackIndex].name, 60 | trackList: state.tracks, 61 | isPlaying: state.isPlaying, 62 | playPreviousTrack, 63 | playNextTrack 64 | }; 65 | }; 66 | 67 | export default useMusicPlayer; 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jojo Zhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Custom Hooks Collection 2 | This is a collection of react custom hooks. I'll update this list if there's any new ones. 3 | 4 | All the hooks are inside CustomHooks folder. 5 | 6 | ## Custom Hook List (links below will direct you to the corresponding hook.js file) 7 | - [useDarkMode](./CustomHooks/useDarkMode.js): includes hook, example Navbar component that uses this hook and CSS that relates to this hook 8 | - [useForm](./CustomHooks/useForm.js): this hook can handle input change and form submission 9 | - [useLocalStorage](./CustomHooks/useLocalStorage.js): can be used with other hooks 10 | - [useMusicPlayer](./CustomHooks/useMusicPlayer.js) 11 | - [useAxios](./CustomHooks/useAxios.js): this hook works together with useLocalStorage hook and axios for data fetching 12 | 13 | 14 | ## License 15 | 16 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details 17 | 18 | #### Made with ❤️ by [Jojo Zhang](https://github.com/nomadkitty) 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------