Article directory
-
- Ordinary use
- Use anti-shake to save money
- The page function is complex and requires value control
- The callback requires some code to be executed immediately, and some code to be executed with anti-shake delay.
-
- useRef
- useCallback
- summary
Normal use
When we use Antd’s input or select to search, the onChange callback will be executed immediately.
import {<!-- --> Input } from "antd"; export default function HomePage() {<!-- --> return ( <div> <Input onChange={<!-- -->(v) => {<!-- --> console.log("value", v.target.value); }} /> </div> ); }
When 123 is entered, the console prints three times
Use anti-shake to save money
When we need to use it with the background, such as background search. In order to reduce the number of interface calls, we often use anti-shake functions for optimization.
import {<!-- --> Input } from "antd"; import {<!-- --> debounce } from "lodash-es"; export default function HomePage() {<!-- --> return ( <div> <Input onChange={<!-- -->debounce((v) => {<!-- --> console.log("value", v.target.value); }, 500)} /> </div> ); }
When each input interval is less than 500ms, input 123, and the console only prints it once.
The page has complex functions and requires value control
When our page is more complex, in addition to itself, other components or pages can also control the display of input content. At this time we need to give input a value to manually control the content of the input.
import {<!-- --> ChangeEvent, useState } from "react"; import {<!-- --> Input } from "antd"; export default function HomePage() {<!-- --> const [value, setValue] = useState("123"); const handleOnchange = (v: ChangeEvent<HTMLInputElement>) => {<!-- --> console.log("value", v.target.value); setValue(v.target.value); }; return ( <div> <Input value={<!-- -->value} onChange={<!-- -->handleOnchange} /> </div> ); }
The initial value is 123, enter 666, and print it three times like the first time.
Add anti-shake function
import {<!-- --> ChangeEvent, useState } from "react"; import {<!-- --> Input } from "antd"; import {<!-- --> debounce } from "lodash-es"; export default function HomePage() {<!-- --> const [value, setValue] = useState("123"); const handleOnchange = debounce((v: ChangeEvent<HTMLInputElement>) => {<!-- --> console.log("value", v.target.value); setValue(v.target.value); }, 500); return ( <div> <Input value={<!-- -->value} onChange={<!-- -->handleOnchange} /> </div> ); }
Although it is printed once, the value has not changed.
I have anti-shaked the change of value, so the value does not change immediately, so the value of onChange is not immediate, so my value can never change.
The callback requires some code to be executed immediately, and some code to be executed with anti-shake delay
In order to solve the previous problem, we need to execute the value change immediately, but the interface request still needs to be executed with anti-shake delay.
import {<!-- --> ChangeEvent, useState } from "react"; import {<!-- --> Input } from "antd"; import {<!-- --> debounce } from "lodash-es"; export default function HomePage() {<!-- --> const [value, setValue] = useState(""); const handleDebounceSearch = debounce((v: string) => {<!-- --> console.log("vv", v); }, 500); const handleOnchange = (v: ChangeEvent<HTMLInputElement>) => {<!-- --> setValue(v.target.value); // Execute immediately handleDebounceSearch(v.target.value); // Anti-shake delay }; return ( <div> <Input value={<!-- -->value} onChange={<!-- -->handleOnchange} /> </div> ); }
The value can be displayed normally, and there is an obvious delay in the printed content, but it is still printed multiple times. Why is this?
The change in state will refresh the component, the functional component will be re-rendered, and the handleDebounceSearch method will be redefined, so the handleDebounceSearch method executed each time onChange is not the same (the reference address is different).
Just fix the reference address of the handleDebounceSearch function.
You can use useRef
or useCallback
useRef
import {<!-- --> ChangeEvent, useEffect, useRef, useState } from "react"; import {<!-- --> Input } from "antd"; import {<!-- --> debounce } from "lodash-es"; export default function HomePage() {<!-- --> const [value, setValue] = useState(""); const handleDebounceSearch = useRef( debounce(async (value: string) => {<!-- --> console.log("vv", value); }, 500) ).current; useEffect(() => {<!-- --> return () => {<!-- --> handleDebounceSearch.cancel(); }; }, []); const handleOnchange = (v: ChangeEvent<HTMLInputElement>) => {<!-- --> setValue(v.target.value); // Execute immediately handleDebounceSearch(v.target.value); // Anti-shake delay }; return ( <div> <Input value={<!-- -->value} onChange={<!-- -->handleOnchange} /> </div> ); }
useCallback
import {<!-- --> ChangeEvent, useCallback, useEffect, useState } from "react"; import {<!-- --> Input } from "antd"; import {<!-- --> debounce } from "lodash-es"; export default function HomePage() {<!-- --> const [value, setValue] = useState(""); const handleDebounceSearch = useCallback( debounce((v: string) => {<!-- --> console.log("vv", v); }, 500), [] ); useEffect(() => {<!-- --> return () => {<!-- --> handleDebounceSearch.cancel(); }; }, []); const handleOnchange = (v: ChangeEvent<HTMLInputElement>) => {<!-- --> setValue(v.target.value); // Execute immediately handleDebounceSearch(v.target.value); // Anti-shake delay }; return ( <div> <Input value={<!-- -->value} onChange={<!-- -->handleOnchange} /> </div> ); }
Note that the timer is cleared when the component is uninstalled
handleDebounceSearch.cancel()
Summary
- The callback function is called frequently and has large request overhead.
- You can use anti-shake methods to solve frequent calls
- Immediate processing of callbacks and anti-shake processing can be processed separately
- Pay attention to the definition of the anti-shake function and whether the reference address is the same.