In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "what are the methods of customizing Hook". In daily operation, I believe that many people have doubts about the methods of customizing Hook. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful for you to answer the questions of "what are the methods of customizing Hook?" Next, please follow the editor to study!
React hooks
React hooks has been introduced into the library in version 16.8. It allows us to use state and other React features in functional components, so we don't even have to write class components.
In fact, Hooks is much more than that.
Hooks can organize the logic within a component into reusable independent units.
Hooks is well suited to the React component model and the new approach to building applications. Hooks can cover all use cases of a class while providing more flexibility to extract, test, and reuse code throughout the application.
Building our own custom React hooks makes it easy to share features among all components of the application, even among different applications, so that we don't have to repeat our work, thus improving the efficiency of building React applications.
Now, take a look at my five most commonly used custom hooks in development and start recreating them so that you can really understand how they work and exactly how to use them to increase productivity and speed up the development process.
Let's go straight to creating our first custom React Hooks.
UseFetch
Getting data is what I do every time I create a React application. I even made a lot of such repeated fetches in one application.
No matter which way we choose to get the data, Axios, Fetch API, or whatever, we are likely to write the same code over and over again in the React component sequence.
So let's look at how to build a simple but useful custom Hook to call that Hook when you need to get data within the application.
Okk, this Hook we call it useFetch.
This Hook accepts two parameters, one is the URL of the query needed to get the data, and the other is the object that represents the option to apply to the request.
Import {useState, useEffect} from 'react'; const useFetch = (url ='', options = null) = > {}; export default useFetch
Getting data is a side effect. Therefore, we should use useEffect Hook to execute the query.
In this example, we use Fetch API to make the request. We will pass URL and options. Once the Promise is resolved, we retrieve the data by parsing the response body. To do this, we use the json () method.
Then we just need to store it in a React state variable.
Import {useState, useEffect} from 'react'; const useFetch = (url ='', options = null) = > {const [data, setData] = useState (null); useEffect () = > {fetch (url, options). Then (res = > res.json ()). Then (data = > setData (data);}, [url, options]);}; export default useFetch
Here, we also need to deal with network errors in case our request goes wrong. So we use another state variable to store the error. This way we can return it from the Hook and determine if an error has occurred.
Import {useState, useEffect} from 'react'; const useFetch = (url ='', options = null) = > {const [data, setData] = useState (null); const [error, setError] = useState (null); useEffect () = > {fetch (url, options) .then (res = > res.json ()) .then (data = > {if (isMounted) {setData (data); setError (null)) ) .catch (error = > {if (isMounted) {setError (error); setData (null);}});}, [url, options]);}; export default useFetch
UseFetch returns an object that contains the data obtained from the URL, or if any error occurs.
Return {error, data}
Finally, it is usually a good practice to show the user the status of the asynchronous request, such as displaying the loading before the result is presented.
Therefore, we add a third state variable to track the status of the request. Set loading to true before the request and to false after the request is completed.
Const useFetch = (url ='', options = null) = > {const [data, setData] = useState (null); const [error, setError] = useState (null); const [loading, setLoading] = useState (false); useEffect () = > {setLoading (true); fetch (url, options) .then (res = > res.json ()) .then data = > {setData (data); setError (null) ) .catch (error = > {setError (error); setData (null);}) .finally () = > setLoading (false));}, [url, options]); return {error, data};}
Now we can return the loading variable so that we can use it to render a loading in the component when the request is running, making it easy for users to know that we are getting the data they are requesting.
Return {loading, error, data}
Before we use userFetch, we have one more thing.
We need to check that the components using our Hook are still mounted to update our state variables. Otherwise, there will be a memory leak.
Import {useState, useEffect} from 'react'; const useFetch = (url ='', options = null) = > {const [data, setData] = useState (null); const [error, setError] = useState (null); const [loading, setLoading] = useState (false); useEffect () = > {let isMounted = true; setLoading (true) Fetch (url, options) .then (res = > res.json ()) .then (data = > {if (isMounted) {setData (data); setError (null);}}) .catch (error = > {if (isMounted) {setError (error); setData (null)) ) .finally (() = > isMounted & & setLoading (false)); return () = > (isMounted = false);}, [url, options]); return {loading, error, data};}; export default useFetch
How do you use it next?
We just need to pass the URL of the resource we want to retrieve. From there, we get an object that we can use to render our application.
Import useFetch from'. / useFetch'; const App = () = > {const {loading, error, data = []} = useFetch ('https://hn.algolia.com/api/v1/search?query=react'); if (error) return
Error!
; if (loading) return
Loading...
; return ({data?.hits?.map (item = > ({item.title}))});}
UseEventListener
This Hook is responsible for setting up and cleaning up event listeners within the component.
In this way, we don't need to add event listeners every time to do repetitive work.
This function takes several parameters, the eventType event type, the listener listener function, the target listener object, and the options optional argument.
Import {useEffect, useRef} from 'react'; const useEventListener = (eventType ='', listener = () = > null, target = null, options = null) = > {}; export default useEventListener
As with the previous Hook, use useEffect to add an event listener. First, we need to make sure that target supports the addEventListener method. Otherwise, we will do nothing.
Import {useEffect, useRef} from 'react'; const useEventListener = (eventType ='', listener = () = > null, target = null, options = null) = > {useEffect (() = > {if (! target?.addEventListener) return;}, [target]);}; export default useEventListener
We can then add the actual event listener and remove it from the uninstall function.
Import {useEffect, useRef} from 'react'; const useEventListener = (eventType ='', listener = () = > null, target = null, options = null) = > {useEffect () = > {if (! target?.addEventListener) return; target.addEventListener (eventType, listener, options); return () = > {target.removeEventListener (eventType, listener, options);};}, [eventType, target, options, listener]);}; export default useEventListener
In fact, we will also use a reference object to store and persist listener functions. We update the reference only when the listener function changes and the reference is used in the event listener method.
Import {useEffect, useRef} from 'react'; const useEventListener = (eventType ='', listener = () = > null, target = null, options = null) = > {const savedListener = useRef (); useEffect () = > {savedListener.current = listener;}, [listener]); useEffect () = > {if (! target?.addEventListener) return; const eventListener = event = > savedListener.current (event); target.addEventListener (eventType, eventListener, options) Return () = > {target.removeEventListener (eventType, eventListener, options);};}, [eventType, target, options];}; export default useEventListener
We don't need to return anything from this Hook, because we just listen for events and run the handler function to pass in as parameters.
It is now easy to add event listeners to our components (such as the following) to detect clicks outside the DOM element. If the user clicks the dialog box component, close the dialog box component here.
Import {useRef} from 'react'; import ReactDOM from' react-dom'; import {useEventListener} from'. / hooks'; const Dialog = ({show = false, onClose = () = > null}) = > {const dialogRef = useRef (); / / Event listener to close dialog on click outside element useEventListener ('mousedown', event = > {if (event.defaultPrevented) {return) / / Do nothing if the event was already processed} if (dialogRef.current & &! dialogRef.current.contains (event.target)) {console.log ('Click outside detected-> closing dialog...'); onClose ();}}, window); return show? ReactDOM.createPortal (What's up {'} YouTube?
, document.body): null;}; export default Dialog
UseLocalStorage
This Hook has two main parameters, one is key and the other is value.
Import {useState} from 'react'; const useLocalStorage = (key ='', initialValue ='') = > {}; export default useLocalStorage
Then, an array is returned, similar to the one obtained using useState. Therefore, this array will contain status values and functions that update them when they are persisted in localStorage.
First, we create a React state variable that will be synchronized with localStorage.
Import {useState} from 'react'; const useLocalStorage = (key ='', initialValue ='') = > {const [state, setState] = useState (() = > {try {const item = window.localStorage.getItem (key); return item? JSON.parse (item): initialValue;} catch (error) {console.log (error); return initialValue;}});}; export default useLocalStorage
Here, we use lazy initialization to read the localStorage to get the value of the key, and if the value is found, it parses the value, otherwise the incoming initialValue is returned.
If an error occurs while reading the localStorage, we only record one error and return the initial value.
Finally, we need to create a update function to return updates to any status that it will store in localStorage, instead of using the default updates returned by useState.
Import {useState} from 'react'; const useLocalStorage = (key ='', initialValue ='') = > {const [state, setState] = useState (() = > {try {const item = window.localStorage.getItem (key); return item? JSON.parse (item): initialValue;} catch (error) {return initialValue;}}); const setLocalStorageState = newState = > {try {const newStateValue = typeof newState = = 'function'? NewState (state): newState; setState (newStateValue); window.localStorage.setItem (key, JSON.stringify (newStateValue));} catch (error) {console.error (`Unable to store new value for ${key} in localStorage.`);}}; return [state, setLocalStorageState];}; export default useLocalStorage
This function updates both the React status and the corresponding key / value in localStorage. Here, we can also support function updates, such as regular useState hook.
Finally, we return the status value and our custom update function.
You can now use useLocalStorage hook to persist any data in the component to localStorage.
Import {useLocalStorage} from'. / hooks'; const defaultSettings = {notifications: 'weekly',}; function App () {const [appSettings, setAppSettings] = useLocalStorage (' app-settings', defaultSettings); return (Your application's settings:
SetAppSettings (settings = > ({... settings, notifications: e.target.value) })} className= "border border-gray-900 rounded py-2 px-4" > daily weekly monthly setAppSettings (defaultSettings)} className= "rounded-md shadow-md py-2 px-6 bg-red-500 text-white uppercase font-medium tracking-wide text-sm leading-8" > Reset settings) } export default App
UseMediaQuery
This Hook helps us to test and monitor media queries programmatically in functional components. This is very useful, for example, when you need to render different UI depending on the type of device or specific features.
Our Hook accepts three parameters:
First of all, the string array corresponding to the media query
Then, match the value arrays of these media queries in the same order as the previous array
Finally, if there is no matching media query, the default value is used
Import {useState, useCallback, useEffect} from 'react'; const useMediaQuery = (queries = [], values = [], defaultValue) = > {}; export default useMediaQuery
The first thing we do in this Hook is to build a media query list for each matching media query. Use this array to get the corresponding value by matching the media query.
Import {useState, useCallback, useEffect} from 'react'; const useMediaQuery = (queries = [], values = [], defaultValue) = > {const mediaQueryList = queries.map (Q = > window.matchMedia (Q));}; export default useMediaQuery
To do this, we created a callback function wrapped in useCallback. Retrieves the value of the first matching media query in the list, and returns the default value if there is no match.
Import {useState, useCallback, useEffect} from 'react'; const useMediaQuery = (queries = [], values = [], defaultValue) = > {const mediaQueryList = queries.map (Q = > window.matchMedia (Q)); const getValue = useCallback (() = > {const index = mediaQueryList.findIndex (mql = > mql.matches); return typeof values [index]! = =' undefined'? Values [index]: defaultValue;}, [mediaQueryList, values, defaultValue]);}; export default useMediaQuery
Then we create a React state to store the matching value and initialize it using the function defined above.
Import {useState, useCallback, useEffect} from 'react'; const useMediaQuery = (queries = [], values = [], defaultValue) = > {const mediaQueryList = queries.map (Q = > window.matchMedia (Q)); const getValue = useCallback (() = > {const index = mediaQueryList.findIndex (mql = > mql.matches); return typeof values [index]! = =' undefined'? Values [index]: defaultValue;}, [mediaQueryList, values, defaultValue]); const [value, setValue] = useState (getValue);}; export default useMediaQuery
Finally, we add an event listener to useEffect to listen for changes to each media query. When a change occurs, we run the update function.
Mport {useState, useCallback, useEffect} from 'react'; const useMediaQuery = (queries = [], values = [], defaultValue) = > {const mediaQueryList = queries.map (Q = > window.matchMedia (Q)); const getValue = useCallback (() = > {const index = mediaQueryList.findIndex (mql = > mql.matches); return typeof values [index]! = =' undefined'? Values [index]: defaultValue;}, [mediaQueryList, values, defaultValue]); const [value, setValue] = useState (getValue); useEffect () = > {const handler = () = > setValue (getValue); mediaQueryList.forEach (mql = > mql.addEventListener ('change', handler)); return () = > mediaQueryList.forEach (mql = > mql.removeEventListener (' change', handler));}, [getValue, mediaQueryList]); return value;}; export default useMediaQuery
A simple example I used recently is to add a media query to check whether the device allows the user to hover over the element. This way, if the user can hover or apply the basic style, I can add a specific opaque style.
Import {useMediaQuery} from'. / hooks'; function App () {const canHover = useMediaQuery (/ / Media queries ['(hover: hover)'], / / Values corresponding to the above media queries by array index [true], / / Default value false); const canHoverClass = 'opacity-0 hover:opacity-100 transition-opacity'; const defaultClass =' opacity-100'; return (Hover me!);} export default App
UseDarkMode
This is my favorite. It can easily and quickly apply dark mode functionality to any React application.
This Hook mainly enables and disables dark mode on demand, storing the current state in localStorage.
To do this, we will use the two hooks we just built: useMediaQuery and useLocalStorage.
Then, using "useLocalStorage", we can initialize, store, and retain the current state (dark or light mode) in localStorage.
Import {useEffect} from 'react'; import useMediaQuery from'. / useMediaQuery'; import useLocalStorage from'. / useLocalStorage'; const useDarkMode = () = > {const preferDarkMode = useMediaQuery ([(prefers-color-scheme: dark)'], [true], false);}; export default useDarkMode
The last part is to trigger side effects to add or remove dark classes from the document.body element. In this way, we can simply apply the dark style to our application.
Import {useEffect} from 'react'; import useMediaQuery from'. / useMediaQuery'; import useLocalStorage from'. / useLocalStorage'; const useDarkMode = () = > {const preferDarkMode = useMediaQuery ([(prefers-color-scheme: dark)'], [true], false); const [enabled, setEnabled] = useLocalStorage ('dark-mode', preferDarkMode); useEffect () = > {if (enabled) {document.body.classList.add (' dark') } else {document.body.classList.remove ('dark');}}, [enabled]); return [enabled, setEnabled];}; export default useDarkMode; at this point, the study of "what are the ways to customize Hook" is over, hoping to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.