๐Ÿš€ [React] react-query์™€ ์„ ์–ธ์ ์ธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ


ํšŒ์‚ฌ์—์„œ ๊ฐœ๋ฐœ ์‹œ์— ์—๋Ÿฌ ์ฒ˜๋ฆฌ๊ฐ€ ๊ณ ๋„ํ™”๋˜์–ด ์žˆ์ง€ ์•Š์•„, ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ๊ฐ€ ํŽ˜์ด์ง€ ์ „์—ญ์œผ๋กœ ํผ์ ธ๋ฒ„๋ ค ์ข‹์ง€ ์•Š์€ ๊ฒฝํ—˜์„ ํ–ˆ์—ˆ๋‹ค.

๋˜ํ•œ ๋‹ค๋“ค ๋งŽ์ด ์‹ ๊ฒฝ์“ฐ๊ณ  ์žˆ์ง€ ์•Š๋Š” ๋ถ€๋ถ„์ด๋‹ค ๋ณด๋‹ˆ ์ฒ˜๋ฆฌ๋„ ์ œ๊ฐ๊ฐ์ด๊ณ  ์–ด๋–ค ๊ณณ์€ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์กฐ์ฐจ ๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ณณ์ด ๋งŽ์•˜๊ธฐ์—, ์ด๋ฅผ ํ•ด๊ฒฐํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋‹ค.

๊ฐœ์š”

React Query Error Handling ์œ„ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ react-query์™€ ํ•จ๊ป˜ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ์กฐ๋ฅผ ์žก์•„๋ณด๊ณ ์ž ํ•œ๋‹ค.

  • ๋‚˜์•„๊ฐ€ ์—๋Ÿฌ๋ฅผ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์•„ ๋กœ๊น…ํ•˜๊ณ  ์ข…๋ฅ˜๋ฅผ ๋‚˜๋ˆ„๊ณ  ์•Œ๋ฆผ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๊ฐ€ ํ•„์š”

๋ชฉํ‘œ

  • ์‚ฌ์šฉ์ž์—๊ฒŒ ์žˆ์–ด ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์„ธ๋ถ„ํ™” ๋œ ์•ˆ๋‚ด ์ œ๊ณต
    • ์˜ˆ์ƒํ•œ ์—๋Ÿฌ(CustomError ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ์—๋Ÿฌ)์™€ ์˜ˆ์ƒํ•˜์ง€ ๋ชป ํ•œ ์—๋Ÿฌ
  • ErrorBoundary๋ฅผ ์กฐ๊ธˆ ๋” ์ž‘์€ ๋‹จ์œ„๋กœ ๊ฐ์‹ธ๋„๋ก ํ•ด์„œ, ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” UI๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ

TL;DR

ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋กœ ์—๋Ÿฌ ์ƒํ™ฉ์„ ๊ตฌ๋ถ„ํ•˜๊ณ  ๊ทธ์— ๋”ฐ๋ฅธ ์ ์ ˆํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๊ณ ์ž ํ–ˆ๋‹ค.

1. ์˜ˆ์ƒํ•œ ์—๋Ÿฌ์ด๊ณ , ์ƒํ™ฉ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ๊ณผ ์ƒˆ๋กœ๊ณ ์นจ UI๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์–ด์š”!

๋„คํŠธ์›Œํฌ ์—๋Ÿฌ์™€ ๊ฐ™์ด ์ผ์‹œ์ ์ธ ์žฅ์•  ์ƒํ™ฉ์ด๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ์‘๋‹ต์„ ์ œ์ถœํ•ด ์ •์ƒ์ ์ธ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ

**ErrorResetBoundary**

  • react-query์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ด๋ถ€์ ์œผ๋กœ react-error-boundary๋ฅผ wrappingํ•œ ์ž์ฒด ErrorBoundary๋ฅผ ์‚ฌ์šฉ์ค‘์ž…๋‹ˆ๋‹ค.
  • onError์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์‘๋‹ต์„ ํ† ์ŠคํŠธ๋กœ ๋„์›๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ์ผ ๊ฒฝ์šฐ(์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ) ์ƒ์œ„ ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋กœ ์—๋Ÿฌ๋ฅผ ๋˜์ง‘๋‹ˆ๋‹ค.
import {
  QueryErrorResetBoundary,
  useQueryErrorResetBoundary,
} from "react-query";

function ErrorResetBoundary({
  children,
  fallbackRender,
  onError,
  onReset,
  ...props
}) {
  const { reset } = useQueryErrorResetBoundary();

  const handleError = (error) => {
    if (!isExpectedError(error)) {
      throw error;
    }

    if (!onError) {
      toast(`์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ${error.response.data.err.msg}`, {
        type: toast.TYPE.ERROR,
      });
    } else {
      onError(error);
    }
  };

  const handleReset = () => {
    if (!onReset) {
      reset(); // ์บ์‹ฑ๋˜์–ด ์žˆ๋Š” ์—๋Ÿฌ๋ฅผ ์ดˆ๊ธฐํ™”
    } else {
      onReset(); // ์ด ๊ฒฝ์šฐ์—๋„ useQueryErrorResetBoundary().reset์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•จ
    }
  };

  return (
    <QueryErrorResetBoundary>
      <ErrorBoundary
        onError={handleError}
        onReset={handleReset}
        fallbackRender={fallbackRender ?? ErrorRetryFallback}
        {...props}
      >
        {children}
      </ErrorBoundary>
    </QueryErrorResetBoundary>
  );
}

Default Fallback

function ErrorRetryFallback({ resetErrorBoundary }) {
  // react-error-boundary์—์„œ ์ž๋™์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š” resetErrorBoundary์„ ํ†ตํ•ด ์—๋Ÿฌ ๋ฆฌ์…‹ ๊ฐ€๋Šฅ

  return <ErrorBox onClick={resetErrorBoundary} />;
}

2. ์˜ˆ์ƒํ•˜์ง€ ๋ชป ํ•œ ์—๋Ÿฌ์ด๊ณ , ํ•ด๋‹น ์—๋Ÿฌ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์–ด์š”!

์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฌธ์˜ํ•  ์ˆ˜ ์žˆ๋Š” UI๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•˜๊ณ , ์ด ๋•Œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

์•ฑ ์ตœ์ƒ๋‹จ์— ๊ฐ์‹ธ๋Š” ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋„ ์ด ๊ฒฝ์šฐ์— ํ•ด๋‹น๋จ

**ErrorBoundary**

  • react-error-boundary๋ฅผ wrappingํ•œ ์ปดํฌ๋„ŒํŠธ
  • onError์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๋ฅผ console.error๋กœ ์ฐ์–ด ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธธ ์ˆ˜ ์žˆ๋‹ค.
  • react-query์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์•„๋ž˜์—์„œ ์„ค๋ช…ํ•˜๋Š” Default Fallback์„ ํ†ตํ•ด ์ „์—ญ์  ์ฒ˜๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
function ErrorBoundary({
  children,
  fallbackRender,
  fallback,
  onError,
  onReset,
  ...props
}) {
  return (
    /**
     * fallback UI props์˜ ์šฐ์„ ์ˆœ์œ„
     * 1. fallback={<CustomFallback />}
     * 2. fallbackRender={() => <CustomFallback />}
     * 3. FallbackComponent={CustomFallback} // ๊ตฌ์กฐ๋ถ„ํ•ด ํ• ๋‹น์ด ๋˜์–ด ์žˆ์ง€ ์•Š์Œ
     *
     * ex1) <ErrorBoundary />
     * : defaultProps๋กœ ์ง€์ •๋˜์–ด ์žˆ๋Š” <ErrorFallback /> ๋ Œ๋”๋ง (fallbackRender)
     *
     * ex2) <ErrorBoundary fallbackRender={() => <MyFallback />} />
     * : <MyFallback /> ๋ Œ๋”๋ง
     *
     * ex3) <ErrorBoundary fallback={<MyFallback />} />
     * : defaultProps๋กœ fallbackRender๊ฐ€ ์ง€์ •๋˜๊ธด ํ•˜์ง€๋งŒ, fallback์˜ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์œผ๋ฏ€๋กœ <MyFallback /> ๋ Œ๋”๋ง
     */
    <ReactErrorBoundary
      fallbackRender={fallbackRender}
      fallback={fallback}
      onError={onError}
      onReset={onReset}
      {...props}
    >
      {children}
    </ReactErrorBoundary>
  );
}

Default Fallback

  • ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ๋ฎ๋Š” fallback
function ErrorFallback({ resetErrorBoundary }) {
  const handleClick = () => {
    resetErrorBoundary();
    history.push(-1);
  };

  return (
    <div className={styles.errorWrapper}>
      <div className={styles.warningBox}>
        <WarningIcon width="28" height="28" />
      </div>
      <div className="text-gray-600">
        ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
        <br /> ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•ด ์ฃผ์„ธ์š”.
      </div>
      <Button onClick={handleClick} color="basic" outline>
        <BackPageIcon />
        ๋’ค๋กœ๊ฐ€๊ธฐ
      </Button>
    </div>
  );
}

react-query๋ฅผ ํ†ตํ•ด ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด ์ „์—ญ์  ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๊ฒฝ์šฐ

  • ์•ฑ๋‹จ์—์„œ queryClient๋ฅผ ์„ ์–ธํ•  ๋•Œ ๊ธ€๋กœ๋ฒŒ ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด fallback UI๋งŒ ์ œ๊ณตํ•  ๋ฟ ์•„๋‹ˆ๋ผ ์ถ”๊ฐ€์ ์œผ๋กœ ์„œ๋ฒ„์—์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ํ† ์ŠคํŠธ๋ฅผ ์ผ๊ด„์ ์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.
const queryClient = new QueryClient({
	queryCache: new QueryCache({
		onError: (err) => {
			handleUnExpectedError(err);
		},
	}),
	mutationCache: new MutationCache({
		onError: (err) => {
			handleUnExpectedError(err);
		},
	}),
	...
});

๊ธฐ์กด ๋ฐฉ์‹์˜ ๋ฌธ์ œ์  ๋ถ„์„ ๋ฐ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ ์ œ์•ˆ

AS-IS

  • ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ ์ ˆํ•œ ๋‹จ์œ„๋กœ ๊ฐ์‹ธ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„, ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ๊ฐ€ ์ „์—ญ์œผ๋กœ ํผ์ ธ ํ™”๋ฉด ์ „์ฒด๋ฅผ ๋ฎ๋Š” fallback ๋ Œ๋”๋ง
  • ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ์‚ฐ์žฌ๋˜์–ด ์žˆ์Œ
    • query, mutation์˜ onError ์ฝœ๋ฐฑ์„ ํ†ตํ•œ ์ง€์—ญ์  ์ฒ˜๋ฆฌ
    • ํŠน์ • ์ปดํฌ๋„ŒํŠธ์—์„œ isError๋ฅผ ํ™•์ธํ•ด ๋ช…๋ น์ ์œผ๋กœ ์ฒ˜๋ฆฌ
    • ์–ด๋–ค ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋„ ๋˜์–ด์žˆ์ง€ ์•Š์•„ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ „์—ญ์œผ๋กœ ์—๋Ÿฌ๊ฐ€ ํผ์ง

TO-BE

์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ ์ ˆํ•œ ๋‹จ์œ„๋กœ ๊ฐ์‹ธ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„, ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ๊ฐ€ ์ „์—ญ์œผ๋กœ ํผ์ ธ ํ™”๋ฉด ์ „์ฒด๋ฅผ ๋ฎ๋Š” fallback ๋ Œ๋”๋ง

TeachConsoleApp ๊ธฐ์ค€์œผ๋กœ PageLayout ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€๋ฅผ ์ ์ ˆํ•œ ๋‹จ์œ„ ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋กœ ๊ฐ์‹ธ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ, ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋ณ€๊ฒฝ

  • ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๊ฒฝ์šฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ์ปดํฌ๋„ŒํŠธ์— ์—๋Ÿฌ๋ฅผ ๊ฐ€๋‘ 
  • retry UI๋ฅผ ์ œ๊ณตํ•˜๋Š” ErrorResetBoundary ์‚ฌ์šฉ ์‹œ์—, ํ•ด๋‹น ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ์—๋Ÿฌ์˜ ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋˜์ ธ ์ƒ์œ„ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ

๋ฐœ์ƒํ•œ ์—๋Ÿฌ์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ์‚ฐ์žฌ๋˜์–ด ์žˆ์Œ

ErrorBoundary์˜ onError๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์ผ์›ํ™”ํ•˜๊ณ , ์ถ”๊ฐ€์ ์œผ๋กœ react-query์˜ queryClient ์„ ์–ธ ์‹œ queryCache, mutationCache์— ๊ธ€๋กœ๋ฒŒ ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•ด ์ „์—ญ์  ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅ

  • isError๋ฅผ ํ™•์ธํ•ด ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ช…๋ น์ ์œผ๋กœ ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ชจ๋‘ ์ œ๊ฑฐ ๊ฐ€๋Šฅ
  • query์˜ onError ์ฝœ๋ฐฑ ์‚ฌ์šฉ ์‹œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์‘์ง‘๋„๊ฐ€ ๋‚ฎ์•„์ง€๋Š” ๊ฒƒ์„ ErrorBoundary์˜ onError๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐ

TkDodo๊ฐ€ ์ถ”์ฒœํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ํ˜„ ๊ตฌ์กฐ ๋ถ„์„

์›ํ•˜๋Š” ๋Œ€๋กœ ํ˜ผํ•ฉํ•˜๊ณ  ์ผ์น˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ฐœ์ธ์ ์œผ๋กœ ํ•˜๊ณ  ์‹ถ์€ ์ผ์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์žฌ๊ฒ€์ƒ‰(์˜ค๋ž˜๋œ UI๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด)์— ๋Œ€ํ•œ ์˜ค๋ฅ˜ ํ† ์ŠคํŠธ๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“  ์ž‘์—…์„ ๋กœ์ปฌ ๋˜๋Š” Error Boundaries๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ธ€ ์ดˆ๋ฐ˜์— ์†Œ๊ฐœํ•œ TkDodo์˜ ๊ฒŒ์‹œ๋ฌผ์„ ํ† ๋Œ€๋กœ ํ˜„ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด์•˜๊ณ  ์–ด๋–ค ๊ฒƒ์ด ๋ฌธ์ œ์ธ์ง€, ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํ•ด์†Œํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ณ ๋ฏผํ•˜๋ฉฐ UX์™€ DX๋ฅผ ๋ชจ๋‘ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์•ˆ์„ ๊ณ ์•ˆํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์˜ฌํ•ด ์ดˆ ErrorBoundary์™€ Suspense๋ฅผ ๋„์ž…ํ•œ ๊ฒƒ์— ์ด์–ด, ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์•ˆ์„ ๊ณ ๋ฏผํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์˜๋ฏธ์žˆ๋Š” ์‹œ๊ฐ„์ด์—ˆ๋‹ค.

์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ๊ฒƒ๋“ค

  • isError ํ”Œ๋ž˜๊ทธ
    • ๋ฐฑ๊ทธ๋ผ์šด๋“œ(re-fetch) ์˜ค๋ฅ˜๋ฅผ ์ž˜ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•จ. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ฆฌํŒจ์น˜๊ฐ€ ์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ ์ฟผ๋ฆฌ๋Š” ์—๋Ÿฌ์™€ ์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์Œ. ์—๋Ÿฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ๋ฐ”๋กœ ์—๋Ÿฌ ์นด๋“œ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ ๋ณด๋‹ค ๋” ๋‹ค์–‘ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ์Œ
  • useQuery์˜ onError ์ฝœ๋ฐฑ
    • ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ์— ์—ฌ๋Ÿฌ ์˜ต์ €๋ฒ„๊ฐ€ ๋ถ™์–ด์žˆ์„ ๊ฒฝ์šฐ onError ์ฝœ๋ฐฑ๋„ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœ๋จ

onError

  • react-error-boundary fallback UI props์˜ ์šฐ์„ ์ˆœ์œ„
    • ๊ธฐ์กด ErrorBoundary๋ฅผ ๊ฐœ์„ ํ•˜๋ฉฐ fallback์˜ ์šฐ์„ ์ˆœ์œ„์— ๋Œ€ํ•ด ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค. ์ด์ „์—๋Š” ์ด๋Ÿฌํ•œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์•Œ ์ง€ ๋ชปํ•ด์„œ ํŠน์ • props๋งŒ ๋ฐ›๋„๋ก ๊ฐ•์ œํ–ˆ์—ˆ๋Š”๋ฐ, ํ•จ๊ป˜ ์ผํ•˜๋Š” ๋™๋ฃŒ๊ฐ€ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ๊นŒ๋ณด๋ฉฐ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์žˆ์—ˆ์Œ์„ ์•Œ๋ ค์ฃผ์—ˆ๋‹ค.

์ŠคํŽ˜์…œ ๋•ก์Šค ํˆฌ. @์ œ๋กœ @๋ฃจํ‚ค

  • ๊ด€๋ จํ•ด์„œ ์ข‹์€ ์˜๊ฒฌ ์ฃผ์…”์„œ ๋” ๋‚˜์€ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ด์š” :>

์ฐธ๊ณ ํ–ˆ๋˜ ๊ธ€ ๋“ค




# ์นดํ…Œ๊ณ ๋ฆฌ