简体   繁体   English

一旦功能组件中的状态发生变化,如何触发钩子?

[英]How to trigger a hook once a state has changed in a functional component?

I'm writing a custom pagination hook that'll fetch an API and will return some data to me like React Query.我正在编写一个自定义分页钩子,它将获取一个 API 并将一些数据返回给我,比如 React Query。 Fairly simple.相当简单。 What I'm trying to do is to trigger that hook when a state(in this case cursor ) updates.我想要做的是在状态(在这种情况下cursor )更新时触发该钩子。

Here's the hook itself:这是钩子本身:

import axios from "../api/axios";
import { useEffect, useRef, useState } from "react";

interface FetchInfiniteResourceProps {
  // The URL of the API endpoint
  url: string;
  // Cursor of the page
  cursor: number;
  // Parameter with which the backend accepts the cursor number
  queryParam: string;
  // The property on the response which will indicate if the next page exists
  nextPageParam: string;

  // Other config
  config: {
    enabled: boolean;
  };
}

// Prop types for useFetchInfiniteResource
interface StateProps {
  data: any[];
  isLoading: boolean;
  hasNextPage: boolean;
  isFetchingNextPage: boolean;
}

/**
 * This function will be used for fetching
 * an infinite resource from the back-end
 */
export const useFetchInfiniteResource = ({
  url,
  cursor,
  queryParam,
  nextPageParam,
  config: { enabled },
}: FetchInfiniteResourceProps) => {
  // Creating a new state
  const [state, setState] = useState<Partial<StateProps>>({
    data: [],
    isLoading: true,
    hasNextPage: false,
    isFetchingNextPage: false,
  });

  // Method for setting the data
  const setData = (newState: []) => setState({ data: newState });

  // The function for sending the request
  const request = async () => {
    // If it's not the first time that this request has triggered
    if (!state.isLoading) setState({ ...state, isFetchingNextPage: true });

    // Sending the request
    const { data: response } = await axios.get(url, {
      params: {
        // Query paramter
        [queryParam]: cursor,
      },
    });

    // Updating the state
    setState({
      // If it's the first time that this request is invoked
      isLoading: state?.isLoading && false,
      // Merging the data
      data: state?.data?.concat(response.data),
      // Checking if the next page exists
      hasNextPage: response[nextPageParam] !== null,
      // If it's not the first time that the request is invoked then set it to false
      isFetchingNextPage: !state?.isLoading && false,
    });
  };

  const requestRef = useRef(async () => await request());

  useEffect(() => {
    if (enabled) requestRef.current();
  }, [enabled]);

  // Returning all the items from the state and the function to update the data manually
  return { ...state, setData };
};

And here's the component:这是组件:

const SomeComponent = () => {
    const [cursor, setCursor] = useState(0);
    const {...} = useFetchInfiniteResource({ cursor, ... }); // Problem here

    someListener(() => {
       setCursor(cursor + 1); // Problem here
    });

    return ...
}

I think I'm misusing the useEffect or the useRef hook, but so far I have tried also using the useCallback hook.我想我误用了 useEffect 或 useRef 钩子,但到目前为止我也尝试过使用 useCallback 钩子。

Thanks for your help谢谢你的帮助

Try wrapping the request function in a useEffect hook with just the cursor in the dependency array.尝试将 request 函数包装在useEffect钩子中,并且只使用依赖项数组中的游标。 ESLint won't like it, but it should work. ESLint 不会喜欢它,但它应该可以工作。

Stripped down example:精简示例:

const useFetchInfiniteResource = ({
  cursor,
  ...
}: FetchInfiniteResourceProps) => {
  const [state, setState] = useState<Partial<StateProps>>({ ... });
 
  const setData = (newState: []) => setState({ data: newState });
 
  useEffect(() => {
    const request = async () => {
      if (!state.isLoading) setState({ ...state, isFetchingNextPage: true });
      const { data: response } = await axios.get(url, {
        params: {
          [queryParam]: cursor,
        },
      });
      setState({ ... });
    };
 
    if (enabled) request();
  }, [cursor]);

  return { ... };
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在功能组件中更改其他 state 后才更改一个 state? - How to make one state change only after other state has been changed in functional component? React 16.7具有状态挂钩,在任何情况下都可以使用功能组件而不是类组件吗? - React 16.7 has State Hook, can I use functional component instead of class component in any situation? 状态更改后功能组件不会重新渲染 - Functional component is not rerendering after state is changed 如何将此 React 钩子组件转换为功能组件 - How to convert this React hook component into a functional component 如何通过钩子 function 反应功能组件 - How to pass hook function to react functional component 当 Select Option Value 改变时触发 Functional React 组件的重新渲染 - Trigger rerender of Functional React Component when Select Option Value is changed 如何在功能性反应组件中洗牌一次数组? - How to shuffle an array once in functional react component? 如何在功能性 React 组件中触发 onScroll - How to trigger onScroll in a functional React component 如何使用 useState - hook 将 class 组件(输入,条件)更改为功能组件? - How to change a class component (input, conditional) to functional component with useState - hook? 在反应组件中,一旦使用 redux 从另一个组件更改状态,如何从状态中获取最新数据? - In a react components, how to get latest data from state once it is changed from another component using redux?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM