From e273f1953a3403d16e4bb272274f55ac4bcd7cd7 Mon Sep 17 00:00:00 2001 From: j3lte Date: Tue, 14 May 2024 10:55:15 +0200 Subject: [PATCH] Better error handling (hooks) --- package.json | 2 +- src/TemplateComponent/index.test.tsx | 2 +- src/TemplateComponent/index.tsx | 74 +++++++++++++++++----------- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 6f55f57..64ab05e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-mustache-template-component", - "version": "2.1.4", + "version": "2.1.5", "description": "Mustache Template Component for React", "author": { "name": "J.W. Lagendijk", diff --git a/src/TemplateComponent/index.test.tsx b/src/TemplateComponent/index.test.tsx index b0bfa49..d9b332b 100644 --- a/src/TemplateComponent/index.test.tsx +++ b/src/TemplateComponent/index.test.tsx @@ -101,7 +101,7 @@ describe("TemplateComponent", () => { ); expect(el).toBeNull(); - expect(mocked).toHaveBeenCalled(); + expect(mocked).toHaveBeenCalledWith(expect.any(Error)); console.error = originalError; }); diff --git a/src/TemplateComponent/index.tsx b/src/TemplateComponent/index.tsx index d04bfd6..a41ed8c 100644 --- a/src/TemplateComponent/index.tsx +++ b/src/TemplateComponent/index.tsx @@ -69,44 +69,58 @@ export interface TemplateComponentProps extends HTMLAttributes { const TemplateComponentInternal: FunctionComponent = forwardRef( ({ template, sanitize, sanitizeOptions, data, type, ...args }, ref) => { - try { - const sanitizer = dompurify.sanitize; - const compiled = useMemo( - () => - typeof template === "string" - ? Mustache.render(template, data) - : null, - [template, data], - ); - const shouldSanitize = typeof sanitize === "boolean" ? sanitize : true; - const innerType = type || "div"; + const sanitizer = dompurify.sanitize; + const shouldSanitize = typeof sanitize === "boolean" ? sanitize : true; + const innerType = type || "div"; + const compiled = useMemo(() => { + if (typeof template === "string") { + try { + return Mustache.render(template, data); + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + return null; + } + } + return null; + }, [template, data]); + + const html = useMemo(() => { if (compiled === null) { return null; } + try { + return ( + shouldSanitize + ? typeof sanitizeOptions !== "undefined" + ? sanitizer(compiled, sanitizeOptions) + : sanitizer(compiled) + : compiled + ) as string; + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + return null; + } + }, [compiled]); - const html = ( - shouldSanitize - ? typeof sanitizeOptions !== "undefined" - ? sanitizer(compiled, sanitizeOptions) - : sanitizer(compiled) - : compiled - ) as string; - - const htmlOpts = useMemo( - () => ({ - ...args, - dangerouslySetInnerHTML: { __html: html }, - }), - [html], - ); + const htmlOpts = useMemo( + () => + html + ? { + ...args, + dangerouslySetInnerHTML: { __html: html }, + } + : args, + [html], + ); - return createElement(innerType, { ...htmlOpts, ref }, null); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); + if (!html) { return null; } + + return createElement(innerType, { ...htmlOpts, ref }, null); }, );