如果使用 useEffect 更改了另一个过滤器,则重置为第一页

Posted

技术标签:

【中文标题】如果使用 useEffect 更改了另一个过滤器,则重置为第一页【英文标题】:reset to first page if another filter is changed with useEffect 【发布时间】:2021-06-04 22:30:29 【问题描述】:

我正在使用 react 功能组件。

要从 api 调用数据,有可用的过滤器和分页。当我更改过滤器类型时,分页必须返回到第一页。

const pageChange = (page) => 
        setPage(page);
    ;

 useEffect(() => 
        async function fetchData() 
            const dateFilter = start && end ? `start=$start&end=$end` : null;
            const pageFilter = `offset=$
        (page - 1) * ITEMS_PER_PAGE
      &limit=$ITEMS_PER_PAGE`;
            const defaultFilters = `$dateFilter?dateFilter:''$dateFilter?'&':''$pageFilter`;
            let request = null;
            switch (type) 
                case "upcoming":
                    request = fetchUpcomingLaunches(defaultFilters);
                    break;
                case "successful":
                    request = fetchLaunches(`$defaultFilters&launch_success=true`);
                    break;
                case "failed":
                    request = fetchLaunches(`$defaultFilters&launch_success=false`);
                    break;
                default:
                    request = fetchLaunches(defaultFilters);
                    break;
            
            try 
                setIsLoading(true);
                const response = await request;
                setItems(getItems(response.data));
                setIsLoading(false);
             catch (err) 
                setIsLoading(false);
            
        
        fetchData();
    , [start, end, type, page]);

我正在使用材质 ui 分页:

   <Pagination
          count=20
          variant="outlined"
          shape="rounded"
          size="large"
          page=page
          onChange=(event, val) => pageChange(val)
        />

这里的开始、结束和类型是过滤器。如果任何过滤器发生变化,则必须调用 api 并刷新数据。 api 必须根据 page 返回分页响应。我的问题是,当任何其他过滤器发生更改时,页面应重置为第一页,并且应从第一页加载数据。是否可以使用两个 useEffect 挂钩?我试过 useEffect 和 type, start, end dependecies 。截至目前,该 api 被调用了两次,因为 setPage 再次被调用。

【问题讨论】:

当我刚开始反应时,我有一个类似的问题here。检查答案中的代码框。 @SuleymanSah 看过了,我不明白它会如何阻止 useEffct 被调用两次 看来你的问题和我的有点不一样。 @SuleymanSah true。实际上,如果我们可以从后端获取项目总数,这个问题将得到解决。分页组件将处理它 这可以解决你的问题:***.com/questions/57240169/… 【参考方案1】:

您需要添加一个带有过滤器依赖项的新 useEffect,并利用useRef 防止过滤器更改时调用两次。

来自answer的想法

const isFilterApplied = useRef(false);

useEffect(() => 
    console.log("Filter change effect")
    isFilterApplied.current = true;
    setCurrentPage(1);
  , [start, end, type]);
  
  useEffect(() => 
    async function fetchData() 
      const dateFilter = start && end ? `start=$start&end=$end` : null;
      const pageFilter = `offset=$(page - 1) * ITEMS_PER_PAGE&limit=$ITEMS_PER_PAGE`;
      const defaultFilters = `$dateFilter ? dateFilter : ""$dateFilter ? "&" : ""$pageFilter`;
      let request = null;
      switch (type) 
        case "upcoming":
          request = fetchUpcomingLaunches(defaultFilters);
          break;
        case "successful":
          request = fetchLaunches(`$defaultFilters&launch_success=true`);
          break;
        case "failed":
          request = fetchLaunches(`$defaultFilters&launch_success=false`);
          break;
        default:
          request = fetchLaunches(defaultFilters);
          break;
      
      try 
        setIsLoading(true);
        const response = await request;
        setItems(getItems(response.data));
        setIsLoading(false);
       catch (err) 
        setIsLoading(false);
      
    

    if (isFilterApplied.current && currentPage !== 1) 
      return;
    

    console.log("Main effect")

    fetchData();
  , [start, end, type, page]);

  useEffect(() => 
    setPage(1);
  , [start, end, type]);

  const changePage = (page) => 
    isFilterApplied.current = false;
    setCurrentPage(page);
  ;

一个示例codesandbox,如果有帮助,可以使用不同的代码库。

【讨论】:

【参考方案2】:

过滤器更改后,您可以将setPage设置为第1页,并在useEffect中添加setPage和条件过滤器。例如

useEffect(() => 
   setPage(1);
,[start, end])

【讨论】:

这个我试过了,这种情况下api会在第一次Useeffect中调用两次,数据会根据哪个请求先返回响应而受到影响 @MohitHarshan 我认为第二个 useEffect 不会导致 API 被调用两次。肯定有其他原因,如果你能在codesandbox中提供你的应用的基本版本,那就很容易找到原因了。 是的,比如dependecy start发生变化,会调用api useeffct,因为它依赖于start,第一次useEffect调用setPage时,会再次调用第二次useEffect@SuleymanSah

以上是关于如果使用 useEffect 更改了另一个过滤器,则重置为第一页的主要内容,如果未能解决你的问题,请参考以下文章

导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect

使用 socket.io 将新的数组更改应用到 useEffect 并更改流

使用快乐的 ESLint 运行一次 useEffect

从 React 中的 useEffect 挂钩更改复选框选中状态?

如何使用 useEffect() 更改 React-Hook-Form defaultValue?

使用 useEffect 渲染的钩子比上一次渲染时更多