next.js useEffect调用函数即使输入未更改[已关闭]

ippsafx7  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(106)

**已关闭。**此问题需要debugging details。它目前不接受回答。

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将有助于其他人回答这个问题。
4天前关闭。
Improve this question
Home.js

export default function Home({ movies }) {
  const [searchTerm, setSearchTerm] = useState("");
  const [inputChanged, setInputChanged] = useState(false);
  const [loading, setLoading] = useState(false);
  const useDelayFuctionRef = useRef(null);
  const router = useRouter();
  const client = {id:'',pass:''}
  useEffect(() => {
    const searchQuery = () => {
      router.push(`${router.pathname}/?search=${searchTerm}`);
    };
    if (inputChanged) {
      useDelayFuctionRef.current = setTimeout(() => {
        searchQuery();
        setInputChanged(false);
        setLoading(false);
      }, 2000);
    }
    return () => {
      clearTimeout(useDelayFuctionRef.current);
      console.log("cleaned");
    };
  }, [searchTerm]);

  return (
    <div>
      <div>
          <input
            type="text"
            onChange={(e) => {
              setSearchTerm(e.target.value);
              setInputChanged(true);
              setLoading(true);
            }}
          />
      </div>
      <div>
        {movies.map((movie) => {
          return (
            <MovieBlock key={movie._id} movie={movie} client={client}/>
          );
        })}
      </div>
    </div>
  );
}

export async function getServerSideProps({ query }) {
  const movies = await fetch(query.string);
  return {
    props: {
      movies,
    },
  };
}

字符串
MovieBlock.js

export default function MovieBlock({ movie, client }) {
  return (
    <div>
      <Link
        key={movie._id}
        href={`/movie/${movie.slug}`}
      >
        <img src={movie.vertical_image} />
      </Link>
      <div>
        <span>
          {movie.genre.map((genre) => <Link key={genre._id} href={`/genre/${genre.slug}`}>{genre.title}</Link>
          }
        </span>
        <span>{movie.title}</span>
      </div>
    </div>
  );
}


当我点击MovieBlock.js中的任何<Link>时,它会等待2秒,然后重定向到被点击的页面链接,useEffectreturn函数在重定向到所需页面后会记录“cleaned”,为什么这种情况会发生在input:onChange以外的重定向上?有没有清理功能?

nc1teljy

nc1teljy1#

您使用useEffect清理函数时遇到的行为与React处理组件卸载和更新的方式有关。
在您的Home组件中,您有一个useEffect钩子,它带有一个包含[searchTerm]的依赖数组。这意味着每当searchTerm更改时,效果就会运行。当您单击MovieBlock.js组件中的<Link>时,它会导航到另一个页面,导致Home组件卸载,然后在加载新页面时重新装载。这种卸载和重新装载会导致useEffect清除功能在卸载组件之前运行。
以下是在这个过程中发生的事情:
1.您键入输入,这将更改searchTerm状态,以2秒的延迟触发useEffect
1.在2秒的延迟过去之前,你点击一个<Link>,这会触发导航到另一个页面。
1.当前的Home组件卸载,因为您正在移动到一个新的页面,并调用useEffect cleanup函数,该函数使用clearTimeout(useDelayFuctionRef.current);清除超时并记录“cleaned”。
1.加载新页面,并重新呈现Home组件,但这次使用了新的状态和属性。
1.由于组件被重新渲染,因此再次设置具有2秒延迟的useEffect,并且对于searchTerm的任何进一步更改重复该过程。
为了避免这种行为,您可以向useEffect钩子添加一个依赖项,这样它就只在组件初始挂载时运行。通过提供一个空的依赖数组([]),效果将只运行一次,相当于类组件中的componentDidMount生命周期方法。
以下是更新后的useEffect

useEffect(() => {
  const searchQuery = () => {
    router.push(`${router.pathname}/?search=${searchTerm}`);
  };
  if (inputChanged) {
    useDelayFuctionRef.current = setTimeout(() => {
      searchQuery();
      setInputChanged(false);
      setLoading(false);
    }, 2000);
  }
  return () => {
    clearTimeout(useDelayFuctionRef.current);
    console.log("cleaned");
  };
}, [searchTerm, inputChanged]); // Add inputChanged as a dependency

字符串
通过包含inputChanged作为依赖项,useEffect也将在inputChanged更改时运行,但由于它是在组件内管理的状态,因此它不会受到导航期间卸载行为的影响。

kqqjbcuj

kqqjbcuj2#

我太笨了,不知道ReactDevTools扩展安装在我的浏览器中♂️(经过一些查找后在stackoverflow上得到了解决方案),尝试在differrect帐户选项卡上运行,它工作得很好

相关问题