12. 在react中使用防抖和節流
1. 原理
爲什麼要使用防抖節流,以及防抖節流的原理可以細看
2. 在React中使用防抖節流錯誤的例子
import React from "react";
import { debounce } from "lodash";
export function ErrorInput() {
const onChange = e => {
console.log(e.target.value);
};
return <input onChange={debounce(onChange, 500)} />;
}
上述代碼看上去沒啥問題,但是我們實際在輸入框中改變Input的值的時候會出現以下報錯
這裏存在的問題是,因爲event事件是同步的,而通過debounce之後,會將多次的事件合併爲一次,進行執行,因此該event性質會被改變不再是同步傳過來的變量了,因此會有該警告
3. 解決辦法
方法一:添加e.persist()。如果按照提示,在調用的函數中添加e.persist(),確實能夠消除該報錯,但是接下來的問題是event.target可能會是null,那麼如果我們在接下來的業務代碼中需要使用到e.target.value就會由問題。因此這個方法不太推薦。
方法二:利用傳參的方法來實現。直接上代碼
import _ from "lodash";
import React, { Component } from "react";
function Search() {
const _handle = value => {
console.log(value);
};
const debounceHandler = _.debounce(_handle, 500);
const onChange = e => {
debounceHandler(e.target.value);
};
return (
<div>
Search:
<input onChange={onChange} />
</div>
);
}
export default Search;
要點總結:
- 設置一個同步處理函數_handle,該函數接受傳來的value值,下面就和普通的回調函數一樣執行業務代碼即可
- 通過一個debounceHandler,調用bounce來生成一個防抖的回調函數
- 定義一個綁定的onChange函數,並指定傳參到debounceHandler中即可
**注意:**這個debonceHandler不能定義在onChange函數內!!!!!非常重要。因爲lodash的debounce是通過閉包來維護一個內部的timer,來控制當指定時間段內,多次事件合併。如果定義在onChange內,每次都會多產生一個閉包環境,仍然會導致多個回調函數被觸發,達不到防抖的效果,切忌切忌
4. 結果展示
上述代碼請查看codesandbox demo