从React应用程序快速连续调用同一端点

时间:2019-09-15 01:25:22

标签: reactjs asynchronous axios use-effect

我有一个名为AddUser的React组件及其父组件AddUsersAddUsers中有一种机制,通过实例化N个AddUser组件,允许一次添加N个用户。

AddUser的字段包括:电子邮件,名字,姓氏。应用程序当前的工作方式是onBlur事件AddUser发起对端点的调用,然后在useEffect构造中处理响应。我在下面提供了所有相关代码。

  // Prepare the useFetch GET call for getting Email Addresses.
  // Note that passing 'null' to useFetch negates the initial call, which is what we want.
  const [{ data: userEmailData, 
           isLoading: userEmailIsLoading, 
           isError: userEmailIsError}, 
           userEmailDoFetch] = useFetch(
    null,
    { }
  )

  // Initiate the doFetch call to check if an e-mail address already exists in the DB
  const handleBlur = (event) => {
    const propName = event.target.name;

    if (propName === 'email') {
      // We'll now check the validation for this element, returning true if okay and false if not.
      if (user.email.trim().length > 0) {
          setIsFetching(true);
          userEmailDoFetch(`${API_ROOT()}acct_mgmt/users/email/${event.target.value}`);
      }
    }
  }

  // Process the response from GET users/email/###
  useEffect(() => {
    setIsFetching(false);
    if (!userEmailIsLoading && user.email.length > 0) {
      const propName = 'email';
      if (userEmailData & !_.isEmpty(userEmailData)) {
        const errorMessage = `This email account is already tied to a user in the system. Please enter a different one.`;
        updateValidationErrors(propName, {type: 'fetch', message: errorMessage});
      } else {
        clearValidationError(propName);
      }
    }
  }, [userEmailIsLoading, userEmailIsError, userEmailData]);

/**
 * Reducer function for all async use... functions herein.
 */
const dataFetchReducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_INIT':
      return { 
        ...state, 
        isLoading: true, 
        isError: false 
      };
    case 'FETCH_SUCCESS':
      return {
        ...state,
        isLoading: false,
        isError: false,
        data: action.payload,
      };
    case 'FETCH_FAILURE':
      return {
        ...state,
        isLoading: false,
        isError: true,
        data: null
      };
    default:
      throw new Error();
  }
}

/**
 * GET data from endpoint using AWS Access Token
 * @param {string} initialUrl   The full path of the endpoint to query
 * @param {JSON}   initialData  Used to initially populate 'data'
 */
export const useFetch = (initialUrl:string, initialData:any) => {
  const [url, setUrl] = useState<string>(initialUrl);
  const { appStore } = useContext(AppContext);

  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false,
    data: initialData
  });

  useEffect(() => {
    let didCancel = false;
    const options = appStore.awsConfig;

    const fetchData = async () => {
      dispatch({ type: 'FETCH_INIT' });

      try {
        let response;
        if (url && options) {
          response = await axios.get(url, options);
        }

        if (!didCancel) {
          dispatch({ type: 'FETCH_SUCCESS', payload: response.data });
        }
      } catch (error) {
        // We won't force an error if there's no URL
        if (!didCancel && url !== null) {
          dispatch({ type: 'FETCH_FAILURE' });
        }
      }
    };

    fetchData();

    return () => {
      didCancel = true;
    };
  }, [url, appStore.awsConfig]);

  return [state, setUrl];
}

需求已更改,因此只有在输入了N个用户的所有电子邮件地址并按了Submit之后,N个呼叫才会打到端点。

我对某些事情感到好奇:如果我要反复呼叫端点,请说检查这些电子邮件地址

abc1@gmail.com
abc2@gmail.com
abc3@gmail.com

是否可以通过单个useEffect构造(不是每个AddUser组件)适当地处理事物,这样将首先返回第一个调用,第二个返回第二个,第三个返回第三个?如果不是,那么您对如何处理404响应的建议是什么?现在,仅将isError设置为true,但没有数据表明哪个请求发出了呼叫。

0 个答案:

没有答案