The onChange callback of the antd component needs to be executed immediately to change the value and anti-shake to save interface overhead.

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.