typescript 如何使React搜索栏组件更快地呈现结果并避免任何内存泄漏?

gzszwxb4  于 2022-12-14  发布在  TypeScript
关注(0)|答案(2)|浏览(166)

当我输入搜索组件时,我注意到有一个延迟,在输入几个字符之后,在第4或第5个字符之后,我会看到一个白色,并且在我的控制台中显示一条消息,指出 “无法在未安装的组件上执行React状态更新。这是一个no-op,但它表明您的应用程序中存在内存泄漏。要修复此问题,取消useEffect清除函数中的所有订阅和异步任务”
我的目标是有一个搜索栏,当有人搜索电影或演员时,它能够正确地呈现所有的结果。
下面是接口的代码:

export interface ActorAttributes {
    TYPE?: string,
    NAME?: string,
}

export interface MovieAttributes {
    OBJECTID: number,
    SID: string,
    NAME: string,
    DIRECTOR: string,
    DESCRIP: string,

应用程序tsx代码:

import { useEffect, useState } from 'react';
import { searchMovies, searchActors, MovieAttributes, ActorAttributes } from "@utils/atts"

const Home: React.FC = () => {
    const [search, setSearch] = useState(false);
    const [movieSearch, setMovieSearch] = useState<MovieAttributes[]>([]);
    const [actorSearch, setActorSearch] = useState<ActorAttributes[]>([]);
    const [searchTerm, setSearchTerm] = useState('');

    useEffect(() => {
        if (searchTerm.length > 0) {
            setSearch(true);

            let newMovieSearch = [...movieSearch];

            searchMovies(searchTerm).then(results => {
                newMovieSearch = results;
                setMovieSearch(results);
            });

            searchActors(searchTerm, newMovieSearch[1].SID).then(results => {
                setActorSearch(results);
            });

            setSearch(false);
        }
    }, [searchTerm]);

    const handleSearchTermChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setSearchTerm(event.target.value);
    }

    return (
        <div>
            <input type="text" value={searchTerm} onChange={handleSearchTermChange} />
            {search && <p>Searching...</p>}
            {movieSearch.length > 0 && <p>Found {movieSearch.length} movies</p>}
            {actorSearch.length > 0 && <p>Found {actorSearch.length} actors</p>}
        </div>
    );
}

目前我只能在我的搜索栏中输入2-3个字符,然后它就会开始延迟和/或我会在我的控制台中收到一个错误消息。我是新的React,这是我第一次创建一个搜索组件,所以如果任何人有任何提示,想法,建议等,请随时留下评论。感谢任何人谁花时间阅读我的帖子:)

<div className="App">
     <ul className="posts">
        <input type="text" onChange={handleSearchTermChange} />
        {movieSearch.map((movie) => {
            if (searchTerm == "" || movie.NAME.toLowerCase().includes(searchTerm.toLowerCase())) {
                return (
                    <li key={movie.OBJECTID}>
                        <h3>{movie.NAME}</h3>
                        <p>{movie.DIRECTOR}</p>
                        <p>{movie.DESCRIP}</p>
                    </li>
                );
             }
            return null;
        )}
    </ul>
</div>
snvhrwxg

snvhrwxg1#

正如其他人所说,如果API调用的结果太大,你可能会遇到问题,如果你知道会抛出很多结果,尝试阻止发送查询(即如果字符串少于3个字符)。除此之外,你可以使用debouncethrottle函数(来自lodash)来阻止每次击键时更新状态。
就像这样:

const delayedQuery = useCallback(
    _.debounce((searchTerm: string) => sendQuery(searchTerm), 500),
    []
  );

沙箱示例:https://codesandbox.io/s/debounce-lodash-ivtm1p?file=/src/App.tsx:1508-1623

6jjcrrmo

6jjcrrmo2#

我想猜到你的问题了。亲爱的,这里有关于这个控制台消息的详细解释**“无法在一个未安装的组件上执行React状态更新。这是一个no-op,但它表明你的应用程序中有内存泄漏。要修复,请取消useEffect清理函数中的所有订阅和异步任务”**我会尽我所能解释得太短,对此我感到抱歉。

**问题:**键入第4到第5个字符后出现白色。
**原因:**当您键入内容时,为每个字符更新“searchTerm”状态,在更新此状态后为每个字符运行useEffect,并且useEffect回调内部具有promise函数,它们是异步函数,因此会导致漏洞应用程序崩溃。
**解决方案简短说明:**不需要任何useEffect。你可以直接使用onChange处理函数中promise函数,就像你的“handleSearchTermChange”一样。请看我的小代码解决方案。我希望你能从这个小代码中得到你的解决方案。

const handleSearchTermChange = (event: any): void => {
    const value = event.target.value;

    if (value.trim() !== "") {
      axios
        .get(`https://example.com/api/v1/product/search?searchProduct=${value}&fields=name`)
        .then((res) => {
          setOptions(res.data.result);
        })
        .catch((e) => {console.log(e)});
    }
  };

在得到承诺的结果后,你可以把这些数据存储在状态中。我不知道你的目的,这就是为什么我没有写在这里其他逻辑。如果你遇到任何问题,请写评论。

相关问题