尝试在 React 项目中实现去抖动
Trying to implement debounce in React Project
我正在尝试在 small/test React 应用程序中实现去抖动。
它只是一个从 API 获取数据的应用程序,它有一个自动完成的文本字段。
import React, { useEffect, useState, useMemo } from 'react';
import axios from 'axios';
const API = 'https://jsonplaceholder.typicode.com/posts';
const AutoComplete2 = () => {
const [ text, setText ] = useState("")
const [ posts, setPosts ] = useState([])
useEffect(() => {
async function fetchData() {
const data = await axios.get(API);
if(parseInt(data.status) !== 200) return;
setPosts(data.data)
}
fetchData();
}, [])
const handleTextChange = (event) => setText(event.target.value);
const handleSelectOption = (str) => setText(str);
const showOptions = useMemo(() => {
if(text === '') return;
const showPosts = [...posts].filter((ele) => ele.title.toLowerCase().includes(text.toLowerCase()));
if(showPosts.length === 1) {
setText(showPosts[0].title);
} else {
return (
<div>
{showPosts.map((obj, index) => {
return (
<div key={index} >
<span onClick={() => handleSelectOption(obj.title)} style={{cursor: 'pointer'}}>
{obj.title}
</span>
</div>
)
})}
</div>
)
}
}, [text, posts])
// addding debounce
const debounce = (fn, delay) => {
let timer;
return function() {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(context, args)
}, delay);
}
}
const newHandleTextChange = ((val) => debounce(handleTextChange(val), 5000));
return (
<div>
<input type="text" value={text} onChange={newHandleTextChange} />
{showOptions}
</div>
)
}
export default AutoComplete2;
应用程序有效,但去抖动无效。我添加了 5 秒的等待时间以清楚地查看它是否正常工作,但每次我更改输入文本时,它都会立即调用该函数。有谁知道为什么会这样?
谢谢
在 React 中去抖动的一种更惯用的方法是使用 useEffect
钩子并将去抖动的文本存储为不同的状态变量。然后,您可以 运行 根据该变量进行过滤。
import React, { useEffect, useState, useMemo } from "react";
import axios from "axios";
const API = "https://jsonplaceholder.typicode.com/posts";
const AutoComplete2 = () => {
const [text, setText] = useState("");
const [debouncedText, setDebouncedText] = useState("");
const [posts, setPosts] = useState([]);
useEffect(() => {
async function fetchData() {
const data = await axios.get(API);
if (parseInt(data.status) !== 200) return;
setPosts(data.data);
}
fetchData();
}, []);
// This will do the debouncing
// "text" will always be current
// "debouncedText" will be debounced
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedText(text);
}, 5000);
// Cleanup function clears timeout
return () => {
clearTimeout(timeout);
};
}, [text]);
const handleTextChange = (event) => setText(event.target.value);
const handleSelectOption = (str) => setText(str);
const showOptions = useMemo(() => {
if (debouncedText === "") return;
const showPosts = [...posts].filter((ele) =>
ele.title.toLowerCase().includes(debouncedText.toLowerCase())
);
if (showPosts.length === 1) {
setText(showPosts[0].title);
} else {
return (
<div>
{showPosts.map((obj, index) => {
return (
<div key={index}>
<span
onClick={() => handleSelectOption(obj.title)}
style={{ cursor: "pointer" }}
>
{obj.title}
</span>
</div>
);
})}
</div>
);
}
}, [debouncedText, posts]);
return (
<div>
<input type="text" value={text} onChange={handleTextChange} />
{showOptions}
</div>
);
};
export default AutoComplete2;
import { useEffect, useState, useRef } from "react";
import axios from "axios";
import { backend_base_url } from "../constants/external_api";
export default function DebounceControlledInput() {
const [search_category_text, setSearchCategoryText] = useState("");
let debounceSearch = useRef();
useEffect(() => {
const debounce = function (fn, interval) {
let timer;
return function (search_key) {
clearTimeout(timer);
timer = setTimeout(() => {
fn(search_key);
}, interval);
};
};
const getCategories = function (search_key) {
axios
.get(`${backend_base_url}categories/${search_key}`)
.then((response) => {
console.log("API Success");
})
.catch((error) => {});
};
debounceSearch.current = debounce(getCategories, 300);
//use for initial load
//debounceSearch.current('');
}, []);
const searchCategory = (search_key) => {
debounceSearch.current(search_key);
};
return (
<form
className="form-inline col-4"
onSubmit={(e) => {
e.preventDefault();
}}
autoComplete="off"
>
<input
type="text"
placeholder=""
id="search"
value={search_category_text}
onChange={(e) => {
searchCategory(e.target.value);
setSearchCategoryText(e.target.value);
e.preventDefault();
}}
/>
</form>
);
}
我正在尝试在 small/test React 应用程序中实现去抖动。
它只是一个从 API 获取数据的应用程序,它有一个自动完成的文本字段。
import React, { useEffect, useState, useMemo } from 'react';
import axios from 'axios';
const API = 'https://jsonplaceholder.typicode.com/posts';
const AutoComplete2 = () => {
const [ text, setText ] = useState("")
const [ posts, setPosts ] = useState([])
useEffect(() => {
async function fetchData() {
const data = await axios.get(API);
if(parseInt(data.status) !== 200) return;
setPosts(data.data)
}
fetchData();
}, [])
const handleTextChange = (event) => setText(event.target.value);
const handleSelectOption = (str) => setText(str);
const showOptions = useMemo(() => {
if(text === '') return;
const showPosts = [...posts].filter((ele) => ele.title.toLowerCase().includes(text.toLowerCase()));
if(showPosts.length === 1) {
setText(showPosts[0].title);
} else {
return (
<div>
{showPosts.map((obj, index) => {
return (
<div key={index} >
<span onClick={() => handleSelectOption(obj.title)} style={{cursor: 'pointer'}}>
{obj.title}
</span>
</div>
)
})}
</div>
)
}
}, [text, posts])
// addding debounce
const debounce = (fn, delay) => {
let timer;
return function() {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(context, args)
}, delay);
}
}
const newHandleTextChange = ((val) => debounce(handleTextChange(val), 5000));
return (
<div>
<input type="text" value={text} onChange={newHandleTextChange} />
{showOptions}
</div>
)
}
export default AutoComplete2;
应用程序有效,但去抖动无效。我添加了 5 秒的等待时间以清楚地查看它是否正常工作,但每次我更改输入文本时,它都会立即调用该函数。有谁知道为什么会这样?
谢谢
在 React 中去抖动的一种更惯用的方法是使用 useEffect
钩子并将去抖动的文本存储为不同的状态变量。然后,您可以 运行 根据该变量进行过滤。
import React, { useEffect, useState, useMemo } from "react";
import axios from "axios";
const API = "https://jsonplaceholder.typicode.com/posts";
const AutoComplete2 = () => {
const [text, setText] = useState("");
const [debouncedText, setDebouncedText] = useState("");
const [posts, setPosts] = useState([]);
useEffect(() => {
async function fetchData() {
const data = await axios.get(API);
if (parseInt(data.status) !== 200) return;
setPosts(data.data);
}
fetchData();
}, []);
// This will do the debouncing
// "text" will always be current
// "debouncedText" will be debounced
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedText(text);
}, 5000);
// Cleanup function clears timeout
return () => {
clearTimeout(timeout);
};
}, [text]);
const handleTextChange = (event) => setText(event.target.value);
const handleSelectOption = (str) => setText(str);
const showOptions = useMemo(() => {
if (debouncedText === "") return;
const showPosts = [...posts].filter((ele) =>
ele.title.toLowerCase().includes(debouncedText.toLowerCase())
);
if (showPosts.length === 1) {
setText(showPosts[0].title);
} else {
return (
<div>
{showPosts.map((obj, index) => {
return (
<div key={index}>
<span
onClick={() => handleSelectOption(obj.title)}
style={{ cursor: "pointer" }}
>
{obj.title}
</span>
</div>
);
})}
</div>
);
}
}, [debouncedText, posts]);
return (
<div>
<input type="text" value={text} onChange={handleTextChange} />
{showOptions}
</div>
);
};
export default AutoComplete2;
import { useEffect, useState, useRef } from "react";
import axios from "axios";
import { backend_base_url } from "../constants/external_api";
export default function DebounceControlledInput() {
const [search_category_text, setSearchCategoryText] = useState("");
let debounceSearch = useRef();
useEffect(() => {
const debounce = function (fn, interval) {
let timer;
return function (search_key) {
clearTimeout(timer);
timer = setTimeout(() => {
fn(search_key);
}, interval);
};
};
const getCategories = function (search_key) {
axios
.get(`${backend_base_url}categories/${search_key}`)
.then((response) => {
console.log("API Success");
})
.catch((error) => {});
};
debounceSearch.current = debounce(getCategories, 300);
//use for initial load
//debounceSearch.current('');
}, []);
const searchCategory = (search_key) => {
debounceSearch.current(search_key);
};
return (
<form
className="form-inline col-4"
onSubmit={(e) => {
e.preventDefault();
}}
autoComplete="off"
>
<input
type="text"
placeholder=""
id="search"
value={search_category_text}
onChange={(e) => {
searchCategory(e.target.value);
setSearchCategoryText(e.target.value);
e.preventDefault();
}}
/>
</form>
);
}