mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-05-24 18:39:12 +00:00
Refactor AreasContextProvider: Add context export, custom hook, PropTypes validation, and error handling
- Added `AreasContext` export and created `useAreasContext` custom hook for safer and easier context access. - Integrated `PropTypes` to validate `children` prop in `AreasContextProvider` component. - Refactored `addArea` function by breaking it into `addExistingArea` and `addNewArea` for improved readability and maintainability. - Added error handling in `deleteArea` function to prevent operations with invalid IDs. - Extracted logic to clear selected element into a separate function for better separation of concerns. - Ensured proper default export for `AreasContextProvider` to facilitate correct imports. These changes improve code robustness, readability, and type safety in the JavaScript environment.
This commit is contained in:
parent
2f26d12f6a
commit
d938f72e1d
51
package-lock.json
generated
51
package-lock.json
generated
@ -43,7 +43,7 @@
|
|||||||
"@types/react-dom": "^18.2.17",
|
"@types/react-dom": "^18.2.17",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"eslint": "^8.55.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
@ -1111,22 +1111,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "8.56.0",
|
"version": "8.57.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
|
||||||
"integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
|
"integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.13",
|
"version": "0.11.14",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
|
||||||
"integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
|
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
|
||||||
|
"deprecated": "Use @eslint/config-array instead",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanwhocodes/object-schema": "^2.0.1",
|
"@humanwhocodes/object-schema": "^2.0.2",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.3.1",
|
||||||
"minimatch": "^3.0.5"
|
"minimatch": "^3.0.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1147,10 +1150,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/object-schema": {
|
"node_modules/@humanwhocodes/object-schema": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
|
||||||
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
|
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
|
||||||
"dev": true
|
"deprecated": "Use @eslint/object-schema instead",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
@ -2317,9 +2322,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001570",
|
"version": "1.0.30001651",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz",
|
||||||
"integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==",
|
"integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -2334,7 +2339,8 @@
|
|||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/ai"
|
"url": "https://github.com/sponsors/ai"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"license": "CC-BY-4.0"
|
||||||
},
|
},
|
||||||
"node_modules/canvg": {
|
"node_modules/canvg": {
|
||||||
"version": "3.0.10",
|
"version": "3.0.10",
|
||||||
@ -2873,16 +2879,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.56.0",
|
"version": "8.57.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
|
||||||
"integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
|
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.6.1",
|
"@eslint-community/regexpp": "^4.6.1",
|
||||||
"@eslint/eslintrc": "^2.1.4",
|
"@eslint/eslintrc": "^2.1.4",
|
||||||
"@eslint/js": "8.56.0",
|
"@eslint/js": "8.57.0",
|
||||||
"@humanwhocodes/config-array": "^0.11.13",
|
"@humanwhocodes/config-array": "^0.11.14",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@nodelib/fs.walk": "^1.2.8",
|
"@nodelib/fs.walk": "^1.2.8",
|
||||||
"@ungap/structured-clone": "^1.2.0",
|
"@ungap/structured-clone": "^1.2.0",
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
"@types/react-dom": "^18.2.17",
|
"@types/react-dom": "^18.2.17",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"eslint": "^8.55.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
import { createContext, useState } from "react";
|
import React, { createContext, useState, ReactNode, useContext } from 'react';
|
||||||
import { Action, ObjectType, defaultBlue } from "../data/constants";
|
import PropTypes from 'prop-types';
|
||||||
import { useUndoRedo, useTransform, useSelect } from "../hooks";
|
import { Action, ObjectType, defaultBlue } from '../data/constants';
|
||||||
import { Toast } from "@douyinfe/semi-ui";
|
import { useUndoRedo, useTransform, useSelect } from '../hooks';
|
||||||
import { useTranslation } from "react-i18next";
|
import { Toast } from '@douyinfe/semi-ui';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const AreasContext = createContext(null);
|
// Define context
|
||||||
|
export const AreasContext = createContext(null); // Ensure export is here
|
||||||
|
|
||||||
export default function AreasContextProvider({ children }) {
|
export const useAreasContext = () => {
|
||||||
|
const context = useContext(AreasContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useAreasContext must be used within an AreasContextProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
// AreasContextProvider component
|
||||||
|
const AreasContextProvider = ({ children }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [areas, setAreas] = useState([]);
|
const [areas, setAreas] = useState([]);
|
||||||
const { transform } = useTransform();
|
const { transform } = useTransform();
|
||||||
@ -15,15 +26,27 @@ export default function AreasContextProvider({ children }) {
|
|||||||
|
|
||||||
const addArea = (data, addToHistory = true) => {
|
const addArea = (data, addToHistory = true) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setAreas((prev) => {
|
addExistingArea(data);
|
||||||
const temp = prev.slice();
|
|
||||||
temp.splice(data.id, 0, data);
|
|
||||||
return temp.map((t, i) => ({ ...t, id: i }));
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
|
addNewArea();
|
||||||
|
}
|
||||||
|
if (addToHistory) {
|
||||||
|
addActionToHistory(Action.ADD, ObjectType.AREA, t("add_area"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addExistingArea = (data) => {
|
||||||
|
setAreas(prev => {
|
||||||
|
const updatedAreas = [...prev];
|
||||||
|
updatedAreas.splice(data.id, 0, data);
|
||||||
|
return updatedAreas.map((area, i) => ({ ...area, id: i }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNewArea = () => {
|
||||||
const width = 200;
|
const width = 200;
|
||||||
const height = 200;
|
const height = 200;
|
||||||
setAreas((prev) => [
|
setAreas(prev => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
id: prev.length,
|
id: prev.length,
|
||||||
@ -35,66 +58,52 @@ export default function AreasContextProvider({ children }) {
|
|||||||
color: defaultBlue,
|
color: defaultBlue,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
|
||||||
if (addToHistory) {
|
|
||||||
setUndoStack((prev) => [
|
|
||||||
...prev,
|
|
||||||
{
|
|
||||||
action: Action.ADD,
|
|
||||||
element: ObjectType.AREA,
|
|
||||||
message: t("add_area"),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
setRedoStack([]);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteArea = (id, addToHistory = true) => {
|
const deleteArea = (id, addToHistory = true) => {
|
||||||
|
if (id < 0 || id >= areas.length) return; // Handle invalid ID
|
||||||
if (addToHistory) {
|
if (addToHistory) {
|
||||||
Toast.success(t("area_deleted"));
|
Toast.success(t("area_deleted"));
|
||||||
setUndoStack((prev) => [
|
addActionToHistory(Action.DELETE, ObjectType.AREA, t("delete_area", areas[id].name), areas[id]);
|
||||||
...prev,
|
|
||||||
{
|
|
||||||
action: Action.DELETE,
|
|
||||||
element: ObjectType.AREA,
|
|
||||||
data: areas[id],
|
|
||||||
message: t("delete_area", areas[id].name),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
setRedoStack([]);
|
|
||||||
}
|
}
|
||||||
setAreas((prev) =>
|
setAreas(prev => {
|
||||||
prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })),
|
const filteredAreas = prev.filter(e => e.id !== id);
|
||||||
);
|
return filteredAreas.map((e, i) => ({ ...e, id: i }));
|
||||||
|
});
|
||||||
if (id === selectedElement.id) {
|
if (id === selectedElement.id) {
|
||||||
setSelectedElement((prev) => ({
|
clearSelectedElement();
|
||||||
...prev,
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearSelectedElement = () => {
|
||||||
|
setSelectedElement({
|
||||||
element: ObjectType.NONE,
|
element: ObjectType.NONE,
|
||||||
id: -1,
|
id: -1,
|
||||||
open: false,
|
open: false,
|
||||||
}));
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateArea = (id, values) => {
|
const updateArea = (id, values) => {
|
||||||
setAreas((prev) =>
|
setAreas(prev => prev.map(area => area.id === id ? { ...area, ...values } : area));
|
||||||
prev.map((t) => {
|
|
||||||
if (t.id === id) {
|
|
||||||
return {
|
|
||||||
...t,
|
|
||||||
...values,
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
return t;
|
const addActionToHistory = (action, element, message, data) => {
|
||||||
}),
|
setUndoStack(prev => [
|
||||||
);
|
...prev,
|
||||||
|
{ action, element, message, data },
|
||||||
|
]);
|
||||||
|
setRedoStack([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AreasContext.Provider
|
<AreasContext.Provider value={{ areas, setAreas, updateArea, addArea, deleteArea }}>
|
||||||
value={{ areas, setAreas, updateArea, addArea, deleteArea }}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</AreasContext.Provider>
|
</AreasContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
AreasContextProvider.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AreasContextProvider;
|
||||||
|
Loading…
Reference in New Issue
Block a user