This article has participated in the “Newcomer Creation Ceremony” activity, and started the road of digging gold creation together.

I read a book called “The Pyramid Principle” and explained the process you need to follow when writing:

Background — conflict — problem — solution

Background:

Why do you need a stabilization function? In the actual development process, when you enter the search box to get the back-end request in real time, you will enter a character to request the back-end.

Conflict:

This is very performance intensive, and we need to optimize it so that when we listen for changes in the input box, it takes 500ms to request the back-end interface once

Question:

So how do we solve this problem

Solution:

Define a stabilization function, to need to draw on the interface method and the time delay timer, to define a timer, return an internal function, inside this judgment Exists if the last time the timer, it is to remove the last timer, then define a new timer, to call incoming function in the timer, I also use apply() to change this and pass args back. I tried using both React class and function components. In the anti-shock function, the class component calls this to the component instance

Custom anti-shake function:

export function debounce(fn, waitTime = 500) {
  let time = null; // Define a timer for the first time
  return function (args) {
    // Inside ordinary functions, arguments are special array objects. Contains a list of arguments when the function is called.
    if (time) {
      clearTimeout(time); // If the last timer exists, the last timer is cleared
    }
    // Set the timer
    time = setTimeout(() = > {
      console.log("this".this); Class components call this to the component instance, functional components do not have this this value is undefined
      fn.apply(this, [args]); //fn calls the window directly, and apply changes this to refer to the calling environment
    }, waitTime);
  };
}
Copy the code

1. Functional components:

export default function DebounceFc() {
  const onSearch = (value: string) = > console.log(value);
  const onChange = (e: React.ChangeEvent<HTMLInputElement>) = > {
    console.log(e.target.value);
    // Call the back-end interface here
  };
  const onChangeDebounce = debounce(onChange, 500); //debounce is passed in when the method is executed and lazy loaded
  return (
    <div style={{ marginTop: 50.marginLeft: 100}} >
      <Search
        placeholder="input search text"
        onSearch={onSearch}
        style={{ width: 200 }}
        onChange={(e)= >OnChangeDebounce (e)} // Call onChangeDebounce when data changes in the input box /></div>
  );
}
Copy the code

Print result:

2. Class components

export class Debounce1 extends Component {
  constructor(props: any) {
    super(props);
    this.onSearch = this.onSearch.bind(this);
    this.onChange = this.onChange.bind(this);
    this.onChangeDebounce = this.onChangeDebounce.bind(this);
    OnChangeDebounce is an intermediate variable. Since onChangeDebounce is called as a callback to onChange, it is called directly instead of through the instance. Therefore, the handler treats the function as a separate function call in the window environment, and its this refers to the global window
    // The this pointer will be lost. To solve this problem, bind(this)
    // So that regardless of how the event handler is passed, this points to the current instantiated object. Instead of bind(this), you can use the arrow function, whose this points to its context
  }
  onSearch(value: string) {
    console.log(value);
  }
  onChange(e: React.ChangeEvent<HTMLInputElement>) {
    console.log(e.target.value);
    // Call the back-end interface here
  }
  onChangeDebounce = debounce(this.onChange, 500); //debounce the method passed for execution and the time of the lazy load
  render() {
    return (
      <div style={{ marginTop: 50.marginLeft: 100}} >
        <Search
          placeholder="input search text"
          onSearch={this.onSearch}
          style={{ width: 200 }}
          onChange={this.onChangeDebounce}// Call when the data in the input box changesonChangeDebounceFunction / >
      </div>); }}Copy the code

Print result:

In addition:

That is because onChangeDebounce is a callback to onChange, so it is not called from an instance. It’s a direct call, so it’s going to process the function, and then it’s going to point to the global window, and the this pointer is going to be lost.

The solution to this problem is to bind(this) when calling a function, so that regardless of how the event handler passes it, this points to the current instantiated object. Instead of bind(this), you can use the arrow function, whose this points to its context. Okay

If the text is wrong, forget big guy point out