diff --git a/.oxlintrc.json b/.oxlintrc.json index a149d115a3b..d59205f7e77 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -57,6 +57,7 @@ "react/jsx-no-target-blank": "error", "react/jsx-fragments": "error", "react/self-closing-comp": "error", + "react/jsx-no-constructed-context-values": "error", "no-lone-blocks": "error", "typescript/prefer-function-type": "error", "typescript/prefer-for-of": "error", @@ -91,6 +92,15 @@ "rules": { "prefer-object-has-own": "off" } + }, + { + "files": [ + "apps/webapp/app/components/primitives/charts/Chart.tsx", + "apps/webapp/app/components/primitives/Timeline.tsx" + ], + "rules": { + "react/jsx-no-constructed-context-values": "off" + } } ] } diff --git a/apps/webapp/app/components/SetupCommands.tsx b/apps/webapp/app/components/SetupCommands.tsx index 54dc2b65293..7d4cc00d0e8 100644 --- a/apps/webapp/app/components/SetupCommands.tsx +++ b/apps/webapp/app/components/SetupCommands.tsx @@ -1,5 +1,5 @@ import { CheckIcon, SparklesIcon } from "@heroicons/react/20/solid"; -import { createContext, useContext, useRef, useState } from "react"; +import { createContext, useContext, useMemo, useRef, useState } from "react"; import { useAppOrigin } from "~/hooks/useAppOrigin"; import { useProject } from "~/hooks/useProject"; import { useTriggerCliTag } from "~/hooks/useTriggerCliTag"; @@ -24,10 +24,13 @@ const PackageManagerContext = createContext ({ activePackageManager, setActivePackageManager }), + [activePackageManager] + ); + return ( - - {children} - + {children} ); } diff --git a/apps/webapp/app/components/primitives/LocaleProvider.tsx b/apps/webapp/app/components/primitives/LocaleProvider.tsx index cb27a03a9f8..c55e6170630 100644 --- a/apps/webapp/app/components/primitives/LocaleProvider.tsx +++ b/apps/webapp/app/components/primitives/LocaleProvider.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from "react"; -import { createContext, useContext } from "react"; +import { createContext, useContext, useMemo } from "react"; type LocaleContext = { locales: string[]; @@ -13,7 +13,7 @@ type LocaleContextProviderProps = { const Context = createContext(null); export const LocaleContextProvider = ({ locales, children }: LocaleContextProviderProps) => { - const value = { locales }; + const value = useMemo(() => ({ locales }), [locales]); return {children}; }; diff --git a/apps/webapp/app/components/primitives/OperatingSystemProvider.tsx b/apps/webapp/app/components/primitives/OperatingSystemProvider.tsx index 7f7f8fc57b6..a50ac25d69e 100644 --- a/apps/webapp/app/components/primitives/OperatingSystemProvider.tsx +++ b/apps/webapp/app/components/primitives/OperatingSystemProvider.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from "react"; -import { createContext, useContext } from "react"; +import { createContext, useContext, useMemo } from "react"; export type OperatingSystemPlatform = "mac" | "windows"; @@ -18,7 +18,9 @@ export const OperatingSystemContextProvider = ({ platform, children, }: OperatingSystemContextProviderProps) => { - return {children}; + const value = useMemo(() => ({ platform }), [platform]); + + return {children}; }; const throwIfNoProvider = () => { diff --git a/apps/webapp/app/components/primitives/SelectedItemsProvider.tsx b/apps/webapp/app/components/primitives/SelectedItemsProvider.tsx index 12f4b68f9ef..260d0d40bb3 100644 --- a/apps/webapp/app/components/primitives/SelectedItemsProvider.tsx +++ b/apps/webapp/app/components/primitives/SelectedItemsProvider.tsx @@ -1,6 +1,6 @@ "use client"; -import { createContext, useCallback, useContext, useReducer } from "react"; +import { createContext, useCallback, useContext, useMemo, useReducer } from "react"; type SelectedItemsContext = { selectedItems: Set; @@ -60,21 +60,14 @@ export function SelectedItemsProvider({ [state] ); + const contextValue = useMemo( + () => ({ selectedItems: state.items, select, deselect, toggle, deselectAll, has, hasAll }), + [state.items, select, deselect, toggle, deselectAll, has, hasAll] + ); + return ( - - {typeof children === "function" - ? children({ - selectedItems: state.items, - select, - deselect, - toggle, - deselectAll, - has, - hasAll, - }) - : children} + + {typeof children === "function" ? children(contextValue) : children} ); } diff --git a/apps/webapp/app/components/primitives/Table.tsx b/apps/webapp/app/components/primitives/Table.tsx index e0dca744935..bd9b2e82185 100644 --- a/apps/webapp/app/components/primitives/Table.tsx +++ b/apps/webapp/app/components/primitives/Table.tsx @@ -1,7 +1,14 @@ import { ChevronDownIcon, ChevronUpDownIcon, ChevronUpIcon } from "@heroicons/react/20/solid"; import { Link } from "@remix-run/react"; import { ClipboardCheckIcon, ClipboardIcon } from "lucide-react"; -import React, { type ReactNode, createContext, forwardRef, useContext, useState } from "react"; +import React, { + type ReactNode, + createContext, + forwardRef, + useContext, + useMemo, + useState, +} from "react"; import { useCopy } from "~/hooks/useCopy"; import { cn } from "~/utils/cn"; import { Popover, PopoverContent, PopoverVerticalEllipseTrigger } from "./Popover"; @@ -84,8 +91,10 @@ export const Table = forwardRef { + const contextValue = useMemo(() => ({ variant }), [variant]); + return ( - +
(defaultStartISO); const [endDate, setEndDate] = useState(defaultEndISO); - const setDateRange = (start: string, end: string) => { + const setDateRange = useCallback((start: string, end: string) => { setStartDate(start); setEndDate(end); - }; + }, []); - const resetDateRange = () => { + const resetDateRange = useCallback(() => { setStartDate(defaultStartISO); setEndDate(defaultEndISO); - }; - - return ( - - {children} - + }, [defaultEndISO, defaultStartISO]); + + const contextValue = useMemo( + () => ({ startDate, endDate, setDateRange, resetDateRange }), + [startDate, endDate, setDateRange, resetDateRange] ); + + return {children}; } export function useDateRange(): DateRangeContextType | null {