Removed React prefix to some use hooks
This commit is contained in:
@@ -19,7 +19,6 @@ import {
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { ConfigProvider } from "antd";
|
||||
import React from "react";
|
||||
import { Locale } from "antd/es/locale";
|
||||
import { languages } from "./i18n";
|
||||
import loadable from "@loadable/component";
|
||||
@@ -28,6 +27,7 @@ import { SpoolmanLayout } from "./components/layout";
|
||||
import liveProvider from "./components/liveProvider";
|
||||
import { getAPIURL, getBasePath } from "./utils/url";
|
||||
import { Favicon } from "./components/favicon";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface ResourcePageProps {
|
||||
resource: "spools" | "filaments" | "vendors";
|
||||
@@ -62,8 +62,8 @@ function App() {
|
||||
};
|
||||
|
||||
// Fetch the antd locale using dynamic imports
|
||||
const [antdLocale, setAntdLocale] = React.useState<Locale | undefined>();
|
||||
React.useEffect(() => {
|
||||
const [antdLocale, setAntdLocale] = useState<Locale | undefined>();
|
||||
useEffect(() => {
|
||||
const fetchLocale = async () => {
|
||||
const locale = await import(
|
||||
`./../node_modules/antd/es/locale/${languages[i18n.language].fullCode.replace("-", "_")}.js`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { LiveEvent } from "@refinedev/core";
|
||||
import React from "react";
|
||||
import liveProvider from "./liveProvider";
|
||||
import { getAPIURL } from "../utils/url";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
|
||||
const liveProviderInstance = liveProvider(getAPIURL());
|
||||
|
||||
@@ -18,22 +18,22 @@ export function useLiveify<Data extends { id: number }>(
|
||||
) {
|
||||
// TODO: The hooks in this function is quite janky, and should be refactored to be more efficient
|
||||
// New state that holds the dataSource with updated values from the live provider
|
||||
const [updatedDataSource, setUpdatedDataSource] = React.useState<Data[]>(dataSource);
|
||||
const [updatedDataSource, setUpdatedDataSource] = useState<Data[]>(dataSource);
|
||||
|
||||
// If the original dataSource changes, update the updatedDataSource
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
setUpdatedDataSource(dataSource);
|
||||
}, [dataSource]);
|
||||
|
||||
// Create a constant reference to itemIds. This is to prevent the useEffect below from triggering extra times.
|
||||
const itemIds = dataSource.map((item) => item.id);
|
||||
const [prevItemIds, setPrevItemIds] = React.useState<number[]>(itemIds);
|
||||
const [prevItemIds, setPrevItemIds] = useState<number[]>(itemIds);
|
||||
if (JSON.stringify(itemIds) !== JSON.stringify(prevItemIds)) {
|
||||
setPrevItemIds(itemIds);
|
||||
}
|
||||
|
||||
// Subscribe to changes for all items in the dataSource
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const subscription = liveProviderInstance?.subscribe({
|
||||
channel: `${resource}-list`,
|
||||
params: {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import { HttpError, IResourceComponentsProps, useInvalidate, useTranslate } from "@refinedev/core";
|
||||
import { Create, useForm, useSelect } from "@refinedev/antd";
|
||||
import { Form, Input, Select, InputNumber, ColorPicker, Button, Typography, Modal, Radio } from "antd";
|
||||
import { Form, Input, Select, InputNumber, ColorPicker, Button, Typography, Radio } from "antd";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { numberFormatter, numberParser } from "../../utils/parsing";
|
||||
import { IVendor } from "../vendors/model";
|
||||
@@ -11,12 +10,11 @@ import { ExtraFieldFormItem, ParsedExtras, StringifiedExtras } from "../../compo
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
|
||||
import { searchMatches } from "../../utils/filtering";
|
||||
import { ExternalFilament, useGetExternalDBFilaments } from "../../utils/queryExternalDB";
|
||||
import { formatFilamentLabel } from "../spools/functions";
|
||||
import { ExternalFilament } from "../../utils/queryExternalDB";
|
||||
import { FilamentImportModal } from "../../components/filamentImportModal";
|
||||
import { getOrCreateVendorFromExternal } from "../vendors/functions";
|
||||
import { MultiColorPicker } from "../../components/multiColorPicker";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
dayjs.extend(utc);
|
||||
|
||||
@@ -32,9 +30,9 @@ export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrClonePr
|
||||
const t = useTranslate();
|
||||
const extraFields = useGetFields(EntityType.filament);
|
||||
const currency = useCurrency();
|
||||
const [isImportExtOpen, setIsImportExtOpen] = React.useState(false);
|
||||
const [isImportExtOpen, setIsImportExtOpen] = useState(false);
|
||||
const invalidate = useInvalidate();
|
||||
const [colorType, setColorType] = React.useState<"single" | "multi">("single");
|
||||
const [colorType, setColorType] = useState<"single" | "multi">("single");
|
||||
|
||||
const { form, formProps, formLoading, onFinish, redirect } = useForm<
|
||||
IFilament,
|
||||
@@ -91,7 +89,7 @@ export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrClonePr
|
||||
|
||||
// Use useEffect to update the form's initialValues when the extra fields are loaded
|
||||
// This is necessary because the form is rendered before the extra fields are loaded
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
extraFields.data?.forEach((field) => {
|
||||
if (formProps.initialValues && field.default_value) {
|
||||
const parsedValue = JSON.parse(field.default_value as string);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { HttpError, IResourceComponentsProps, useTranslate } from "@refinedev/core";
|
||||
import { Edit, useForm, useSelect } from "@refinedev/antd";
|
||||
import { Form, Input, DatePicker, Select, InputNumber, ColorPicker, message, Alert, Typography, Radio } from "antd";
|
||||
@@ -26,7 +26,7 @@ export const FilamentEdit: React.FC<IResourceComponentsProps> = () => {
|
||||
const [hasChanged, setHasChanged] = useState(false);
|
||||
const extraFields = useGetFields(EntityType.filament);
|
||||
const currency = useCurrency();
|
||||
const [colorType, setColorType] = React.useState<"single" | "multi">("single");
|
||||
const [colorType, setColorType] = useState<"single" | "multi">("single");
|
||||
|
||||
const { formProps, saveButtonProps } = useForm<IFilament, HttpError, IFilament, IFilament>({
|
||||
liveMode: "manual",
|
||||
@@ -52,7 +52,7 @@ export const FilamentEdit: React.FC<IResourceComponentsProps> = () => {
|
||||
}
|
||||
|
||||
// Update colorType state
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
console.log(formProps.initialValues?.multi_color_hexes);
|
||||
if (formProps.initialValues?.multi_color_hexes) {
|
||||
setColorType("multi");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { IResourceComponentsProps, useTranslate, useInvalidate, useNavigation } from "@refinedev/core";
|
||||
import { useTable, List } from "@refinedev/antd";
|
||||
import { Table, Button, Dropdown } from "antd";
|
||||
@@ -125,7 +125,7 @@ export const FilamentList: React.FC<IResourceComponentsProps> = () => {
|
||||
});
|
||||
|
||||
// Create state for the columns to show
|
||||
const [showColumns, setShowColumns] = React.useState<string[]>(initialState.showColumns ?? defaultColumns);
|
||||
const [showColumns, setShowColumns] = useState<string[]>(initialState.showColumns ?? defaultColumns);
|
||||
|
||||
// Store state in local storage
|
||||
const tableState: TableState = {
|
||||
@@ -137,7 +137,7 @@ export const FilamentList: React.FC<IResourceComponentsProps> = () => {
|
||||
useStoreInitialState(namespace, tableState);
|
||||
|
||||
// Collapse the dataSource to a mutable list
|
||||
const queryDataSource: IFilamentCollapsed[] = React.useMemo(
|
||||
const queryDataSource: IFilamentCollapsed[] = useMemo(
|
||||
() => (tableProps.dataSource || []).map((record) => ({ ...record })),
|
||||
[tableProps.dataSource]
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Table, Checkbox, Space, Row, Col, message, Button } from "antd";
|
||||
import { ISpool } from "../spools/model";
|
||||
import { FilteredQueryColumn, SortedColumn, SpoolIconColumn } from "../../components/column";
|
||||
@@ -79,7 +79,7 @@ const SpoolSelectModal: React.FC<Props> = ({ description, onContinue }) => {
|
||||
};
|
||||
|
||||
// Collapse the dataSource to a mutable list and add a filament_name field
|
||||
const dataSource: ISpoolCollapsed[] = React.useMemo(
|
||||
const dataSource: ISpoolCollapsed[] = useMemo(
|
||||
() => (tableProps.dataSource || []).map((record) => ({ ...record })),
|
||||
[tableProps.dataSource]
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslate } from "@refinedev/core";
|
||||
import { Button, Form, Input, message } from "antd";
|
||||
import { useGetSettings, useSetSetting } from "../../utils/querySettings";
|
||||
@@ -11,7 +11,7 @@ export function GeneralSettings() {
|
||||
const t = useTranslate();
|
||||
|
||||
// Set initial form values
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (settings.data) {
|
||||
form.setFieldsValue({
|
||||
currency: JSON.parse(settings.data.currency.value),
|
||||
@@ -20,7 +20,7 @@ export function GeneralSettings() {
|
||||
}, [settings.data, form]);
|
||||
|
||||
// Popup message if setSetting is successful
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (setCurrency.isSuccess) {
|
||||
messageApi.success(t("notifications.saveSuccessful"));
|
||||
}
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { HttpError, IResourceComponentsProps, useTranslate } from "@refinedev/core";
|
||||
import { Create, useForm, useSelect } from "@refinedev/antd";
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
DatePicker,
|
||||
Select,
|
||||
InputNumber,
|
||||
Radio,
|
||||
Divider,
|
||||
Button,
|
||||
Typography,
|
||||
ConfigProvider,
|
||||
Alert,
|
||||
Space,
|
||||
} from "antd";
|
||||
import { Create, useForm } from "@refinedev/antd";
|
||||
import { Form, Input, DatePicker, Select, InputNumber, Radio, Divider, Button, Typography, Alert } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { IFilament } from "../filaments/model";
|
||||
import { ISpool, ISpoolParsedExtras, WeightToEnter } from "./model";
|
||||
import { formatLength, formatWeight, numberFormatter, numberParser } from "../../utils/parsing";
|
||||
import { numberFormatter, numberParser } from "../../utils/parsing";
|
||||
import { useSpoolmanLocations } from "../../components/otherModels";
|
||||
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import "../../utils/overrides.css";
|
||||
@@ -27,9 +13,8 @@ import { EntityType, useGetFields } from "../../utils/queryFields";
|
||||
import { ExtraFieldFormItem, ParsedExtras, StringifiedExtras } from "../../components/extraFields";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
|
||||
import { ExternalFilament, useGetExternalDBFilaments } from "../../utils/queryExternalDB";
|
||||
import { createFilamentFromExternal } from "../filaments/functions";
|
||||
import { formatFilamentLabel, useGetFilamentSelectOptions } from "./functions";
|
||||
import { useGetFilamentSelectOptions } from "./functions";
|
||||
import { searchMatches } from "../../utils/filtering";
|
||||
|
||||
dayjs.extend(utc);
|
||||
@@ -145,7 +130,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
||||
|
||||
// Use useEffect to update the form's initialValues when the extra fields are loaded
|
||||
// This is necessary because the form is rendered before the extra fields are loaded
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
extraFields.data?.forEach((field) => {
|
||||
if (formProps.initialValues && field.default_value) {
|
||||
const parsedValue = JSON.parse(field.default_value as string);
|
||||
@@ -161,7 +146,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
||||
const [weightToEnter, setWeightToEnter] = useState(1);
|
||||
const [usedWeight, setUsedWeight] = useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const newFilamentWeight = selectedFilament?.weight || 0;
|
||||
const newSpoolWeight = selectedFilament?.spool_weight || 0;
|
||||
if (newFilamentWeight > 0) {
|
||||
@@ -242,7 +227,7 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
|
||||
return selectedFilament?.weight ? true : false;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (weightToEnter >= WeightToEnter.measured_weight) {
|
||||
if (!isMeasuredWeightEnabled()) {
|
||||
setWeightToEnter(WeightToEnter.remaining_weight);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { HttpError, IResourceComponentsProps, useTranslate } from "@refinedev/core";
|
||||
import { Edit, useForm, useSelect } from "@refinedev/antd";
|
||||
import { Edit, useForm } from "@refinedev/antd";
|
||||
import { Form, Input, DatePicker, Select, InputNumber, Radio, Divider, Alert, Typography } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { IFilament } from "../filaments/model";
|
||||
import { ISpool, ISpoolParsedExtras, WeightToEnter } from "./model";
|
||||
import { numberFormatter, numberParser } from "../../utils/parsing";
|
||||
import { useSpoolmanLocations } from "../../components/otherModels";
|
||||
@@ -117,7 +116,7 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
||||
const [weightToEnter, setWeightToEnter] = useState(1);
|
||||
const [usedWeight, setUsedWeight] = useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const newFilamentWeight = selectedFilament?.weight || 0;
|
||||
const newSpoolWeight = selectedFilament?.spool_weight || 0;
|
||||
console.log("selectedFilament", selectedFilament, newFilamentWeight, newSpoolWeight);
|
||||
@@ -190,7 +189,7 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
|
||||
return selectedFilament?.weight ? true : false;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (weightToEnter >= WeightToEnter.measured_weight) {
|
||||
if (!isMeasuredWeightEnabled()) {
|
||||
setWeightToEnter(WeightToEnter.remaining_weight);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useMemo } from "react";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { IResourceComponentsProps, useInvalidate, useNavigation, useTranslate } from "@refinedev/core";
|
||||
import { useTable, List } from "@refinedev/antd";
|
||||
import { Table, Button, Dropdown, Modal } from "antd";
|
||||
@@ -159,7 +159,7 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
|
||||
});
|
||||
|
||||
// Create state for the columns to show
|
||||
const [showColumns, setShowColumns] = React.useState<string[]>(initialState.showColumns ?? defaultColumns);
|
||||
const [showColumns, setShowColumns] = useState<string[]>(initialState.showColumns ?? defaultColumns);
|
||||
|
||||
// Store state in local storage
|
||||
const tableState: TableState = {
|
||||
@@ -171,7 +171,7 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
|
||||
useStoreInitialState(namespace, tableState);
|
||||
|
||||
// Collapse the dataSource to a mutable list
|
||||
const queryDataSource: ISpoolCollapsed[] = React.useMemo(
|
||||
const queryDataSource: ISpoolCollapsed[] = useMemo(
|
||||
() => (tableProps.dataSource || []).map((record) => ({ ...record })),
|
||||
[tableProps.dataSource]
|
||||
);
|
||||
|
||||
4
client/src/pages/vendors/create.tsx
vendored
4
client/src/pages/vendors/create.tsx
vendored
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { HttpError, IResourceComponentsProps, useTranslate } from "@refinedev/core";
|
||||
import { Create, useForm } from "@refinedev/antd";
|
||||
import { Button, Form, Input, Typography, InputNumber } from "antd";
|
||||
@@ -43,7 +43,7 @@ export const VendorCreate: React.FC<IResourceComponentsProps & CreateOrCloneProp
|
||||
|
||||
// Use useEffect to update the form's initialValues when the extra fields are loaded
|
||||
// This is necessary because the form is rendered before the extra fields are loaded
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
extraFields.data?.forEach((field) => {
|
||||
if (formProps.initialValues && field.default_value) {
|
||||
const parsedValue = JSON.parse(field.default_value as string);
|
||||
|
||||
6
client/src/pages/vendors/list.tsx
vendored
6
client/src/pages/vendors/list.tsx
vendored
@@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
import { IResourceComponentsProps, useTranslate, useInvalidate, useNavigation } from "@refinedev/core";
|
||||
import { useTable, List } from "@refinedev/antd";
|
||||
import { Table, Button, Dropdown } from "antd";
|
||||
@@ -19,6 +18,7 @@ import { useLiveify } from "../../components/liveify";
|
||||
import { removeUndefined } from "../../utils/filtering";
|
||||
import { EntityType, useGetFields } from "../../utils/queryFields";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
dayjs.extend(utc);
|
||||
|
||||
@@ -66,7 +66,7 @@ export const VendorList: React.FC<IResourceComponentsProps> = () => {
|
||||
});
|
||||
|
||||
// Create state for the columns to show
|
||||
const [showColumns, setShowColumns] = React.useState<string[]>(initialState.showColumns ?? allColumns);
|
||||
const [showColumns, setShowColumns] = useState<string[]>(initialState.showColumns ?? allColumns);
|
||||
|
||||
// Store state in local storage
|
||||
const tableState: TableState = {
|
||||
@@ -78,9 +78,9 @@ export const VendorList: React.FC<IResourceComponentsProps> = () => {
|
||||
useStoreInitialState(namespace, tableState);
|
||||
|
||||
// Collapse the dataSource to a mutable list
|
||||
const queryDataSource: IVendor[] = React.useMemo(
|
||||
() => (tableProps.dataSource || []).map((record) => ({ ...record })),
|
||||
[tableProps.dataSource]
|
||||
const queryDataSource: IVendor[] = useMemo(
|
||||
);
|
||||
const dataSource = useLiveify("vendor", queryDataSource, (record: IVendor) => record);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { CrudFilter, CrudSort } from "@refinedev/core";
|
||||
import { isLocalStorageAvailable } from "./support";
|
||||
import { useEffect, useState } from "react";
|
||||
interface Pagination {
|
||||
current: number;
|
||||
pageSize: number;
|
||||
@@ -14,7 +14,7 @@ export interface TableState {
|
||||
}
|
||||
|
||||
export function useInitialTableState(tableId: string): TableState {
|
||||
const [initialState] = React.useState(() => {
|
||||
const [initialState] = useState(() => {
|
||||
const savedSorters = hasHashProperty("sorters")
|
||||
? getHashProperty("sorters")
|
||||
: isLocalStorageAvailable
|
||||
@@ -42,7 +42,7 @@ export function useInitialTableState(tableId: string): TableState {
|
||||
}
|
||||
|
||||
export function useStoreInitialState(tableId: string, state: TableState) {
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (state.sorters.length > 0 && JSON.stringify(state.sorters) != JSON.stringify([{ field: "id", order: "asc" }])) {
|
||||
if (isLocalStorageAvailable) {
|
||||
localStorage.setItem(`${tableId}-sorters`, JSON.stringify(state.sorters));
|
||||
@@ -54,7 +54,7 @@ export function useStoreInitialState(tableId: string, state: TableState) {
|
||||
}
|
||||
}, [tableId, state.sorters]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const filters = state.filters.filter((f) => f.value.length != 0);
|
||||
if (filters.length > 0) {
|
||||
if (isLocalStorageAvailable) {
|
||||
@@ -67,7 +67,7 @@ export function useStoreInitialState(tableId: string, state: TableState) {
|
||||
}
|
||||
}, [tableId, state.filters]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (JSON.stringify(state.pagination) != JSON.stringify({ current: 1, pageSize: 20 })) {
|
||||
if (isLocalStorageAvailable) {
|
||||
localStorage.setItem(`${tableId}-pagination`, JSON.stringify(state.pagination));
|
||||
@@ -79,7 +79,7 @@ export function useStoreInitialState(tableId: string, state: TableState) {
|
||||
}
|
||||
}, [tableId, state.pagination]);
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (isLocalStorageAvailable) {
|
||||
if (state.showColumns === undefined) {
|
||||
localStorage.removeItem(`${tableId}-showColumns`);
|
||||
@@ -91,12 +91,12 @@ export function useStoreInitialState(tableId: string, state: TableState) {
|
||||
}
|
||||
|
||||
export function useSavedState<T>(id: string, defaultValue: T) {
|
||||
const [state, setState] = React.useState<T>(() => {
|
||||
const [state, setState] = useState<T>(() => {
|
||||
const savedState = isLocalStorageAvailable ? localStorage.getItem(`savedStates-${id}`) : null;
|
||||
return savedState ? JSON.parse(savedState) : defaultValue;
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (isLocalStorageAvailable) {
|
||||
localStorage.setItem(`savedStates-${id}`, JSON.stringify(state));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user