use 'useShallow' to optimize selector

This commit is contained in:
codetypes committed 2025-03-13 12:54:51 +08:00
1 parent fb889a01c8
commit 61431893bf
6 files changed
+99 -79

No files matched your search

+12 -9
View File
@@ -13,6 +13,7 @@ import { RiFocus3Line } from "react-icons/ri";
import { VscCaseSensitive } from "react-icons/vsc"; import { VscCaseSensitive } from "react-icons/vsc";
import { mergeRefs } from "react-merge-refs"; import { mergeRefs } from "react-merge-refs";
import { useDebounceCallback } from "usehooks-ts"; import { useDebounceCallback } from "usehooks-ts";
import { useShallow } from "zustand/react/shallow";
import { import {
EditEvent, EditEvent,
EditNode, EditNode,
@@ -161,15 +162,17 @@ const createMenu = () => {
}; };
export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, ...props }) => { export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, ...props }) => {
const workspace = { const workspace = useWorkspace(
editing: useWorkspace((state) => state.editing), useShallow((state) => ({
onEditingNode: useWorkspace((state) => state.onEditingNode), editing: state.editing,
onEditingTree: useWorkspace((state) => state.onEditingTree), onEditingNode: state.onEditingNode,
open: useWorkspace((state) => state.open), onEditingTree: state.onEditingTree,
workdir: useWorkspace((state) => state.workdir), open: state.open,
relative: useWorkspace((state) => state.relative), workdir: state.workdir,
updateFileMeta: useWorkspace((state) => state.updateFileMeta), relative: state.relative,
}; updateFileMeta: state.updateFileMeta,
}))
);
const searchInputRef = useRef<InputRef>(null); const searchInputRef = useRef<InputRef>(null);
const graphRef = useRef(null); const graphRef = useRef(null);
+14 -11
View File
@@ -10,6 +10,7 @@ import { FaExclamationTriangle, FaSwatchbook } from "react-icons/fa";
import { FiCommand, FiDelete } from "react-icons/fi"; import { FiCommand, FiDelete } from "react-icons/fi";
import { IoMdReturnLeft } from "react-icons/io"; import { IoMdReturnLeft } from "react-icons/io";
import { PiTreeStructureFill } from "react-icons/pi"; import { PiTreeStructureFill } from "react-icons/pi";
import { useShallow } from "zustand/react/shallow";
import { NodeDef } from "../behavior3/src/behavior3"; import { NodeDef } from "../behavior3/src/behavior3";
import { FileTreeType, useWorkspace } from "../contexts/workspace-context"; import { FileTreeType, useWorkspace } from "../contexts/workspace-context";
import { getNodeType } from "../misc/b3type"; import { getNodeType } from "../misc/b3type";
@@ -273,17 +274,19 @@ const createFolderContextMenu = (copiedPath: string) => {
}; };
export const Explorer: FC = () => { export const Explorer: FC = () => {
const workspace = { const workspace = useWorkspace(
close: useWorkspace((state) => state.close), useShallow((state) => ({
editing: useWorkspace((state) => state.editing), close: state.close,
editingNodeDef: useWorkspace((state) => state.editingNodeDef), editing: state.editing,
editors: useWorkspace((state) => state.editors), editingNodeDef: state.editingNodeDef,
fileTree: useWorkspace((state) => state.fileTree), editors: state.editors,
nodeDefs: useWorkspace((state) => state.nodeDefs), fileTree: state.fileTree,
workdir: useWorkspace((state) => state.workdir), nodeDefs: state.nodeDefs,
onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef), workdir: state.workdir,
open: useWorkspace((state) => state.open), onEditingNodeDef: state.onEditingNodeDef,
}; open: state.open,
}))
);
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
const [expandedKeys, setExpandedKeys] = useState<React.Key[]>( const [expandedKeys, setExpandedKeys] = useState<React.Key[]>(
+24 -16
View File
@@ -16,6 +16,7 @@ import { FC, useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import { useDebounceCallback } from "usehooks-ts"; import { useDebounceCallback } from "usehooks-ts";
import { useShallow } from "zustand/react/shallow";
import { EditNode, EditTree, useWorkspace } from "../contexts/workspace-context"; import { EditNode, EditTree, useWorkspace } from "../contexts/workspace-context";
import { import {
isBoolType, isBoolType,
@@ -44,10 +45,12 @@ interface OptionType extends DefaultOptionType {
} }
const TreeInspector: FC = () => { const TreeInspector: FC = () => {
const workspace = { const workspace = useWorkspace(
editing: useWorkspace((state) => state.editing), useShallow((state) => ({
editingTree: useWorkspace((state) => state.editingTree)!, editing: state.editing,
}; editingTree: state.editingTree!,
}))
);
const { t } = useTranslation(); const { t } = useTranslation();
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -101,15 +104,18 @@ const TreeInspector: FC = () => {
}; };
const NodeInspector: FC = () => { const NodeInspector: FC = () => {
const workspace = { const workspace = useWorkspace(
editing: useWorkspace((state) => state.editing), useShallow((state) => ({
editingNode: useWorkspace((state) => state.editingNode)!, editing: state.editing,
nodeDefs: useWorkspace((state) => state.nodeDefs), editingNode: state.editingNode!,
onEditingNode: useWorkspace((state) => state.onEditingNode), nodeDefs: state.nodeDefs,
allFiles: useWorkspace((state) => state.allFiles), allFiles: state.allFiles,
fileTree: useWorkspace((state) => state.fileTree), fileTree: state.fileTree,
relative: useWorkspace((state) => state.relative), relative: state.relative,
}; onEditingNode: state.onEditingNode,
}))
);
const { t } = useTranslation(); const { t } = useTranslation();
const [form] = Form.useForm(); const [form] = Form.useForm();
@@ -920,9 +926,11 @@ const NodeInspector: FC = () => {
}; };
const NodeDefInspector: FC = () => { const NodeDefInspector: FC = () => {
const workspace = { const workspace = useWorkspace(
editingNodeDef: useWorkspace((state) => state.editingNodeDef)!, useShallow((state) => ({
}; editingNodeDef: state.editingNodeDef!,
}))
);
const { t } = useTranslation(); const { t } = useTranslation();
const [form] = Form.useForm(); const [form] = Form.useForm();
const def = workspace.editingNodeDef.data; const def = workspace.editingNodeDef.data;
+16 -13
View File
@@ -8,6 +8,7 @@ import * as fs from "fs";
import { FC, useMemo, useState } from "react"; import { FC, useMemo, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PiTreeStructureFill } from "react-icons/pi"; import { PiTreeStructureFill } from "react-icons/pi";
import { useShallow } from "zustand/react/shallow";
import { useSetting } from "../contexts/setting-context"; import { useSetting } from "../contexts/setting-context";
import { useWorkspace } from "../contexts/workspace-context"; import { useWorkspace } from "../contexts/workspace-context";
import * as b3util from "../misc/b3util"; import * as b3util from "../misc/b3util";
@@ -40,19 +41,21 @@ ipcRenderer.on("refresh-app-men", () => {
export const Menu: FC<LayoutProps> = () => { export const Menu: FC<LayoutProps> = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [trigger, setTrigger] = useState<DropDownProps["trigger"]>(["click"]); const [trigger, setTrigger] = useState<DropDownProps["trigger"]>(["click"]);
const workspace = { const workspace = useWorkspace(
batchProject: useWorkspace((state) => state.batchProject), useShallow((state) => ({
buildProject: useWorkspace((state) => state.buildProject), batchProject: state.batchProject,
createProject: useWorkspace((state) => state.createProject), buildProject: state.buildProject,
editing: useWorkspace((state) => state.editing), createProject: state.createProject,
init: useWorkspace((state) => state.init), editing: state.editing,
open: useWorkspace((state) => state.open), init: state.init,
openProject: useWorkspace((state) => state.openProject), open: state.open,
path: useWorkspace((state) => state.path), openProject: state.openProject,
save: useWorkspace((state) => state.save), path: state.path,
saveAll: useWorkspace((state) => state.saveAll), save: state.save,
workdir: useWorkspace((state) => state.workdir), saveAll: state.saveAll,
}; workdir: state.workdir,
}))
);
const enabled = !!workspace.workdir; const enabled = !!workspace.workdir;
const homedir = app.getPath("home"); const homedir = app.getPath("home");
const settings = { const settings = {
+14 -11
View File
@@ -1,6 +1,7 @@
import { SearchOutlined } from "@ant-design/icons"; import { SearchOutlined } from "@ant-design/icons";
import { Button, Flex, LayoutProps, Select } from "antd"; import { Button, Flex, LayoutProps, Select } from "antd";
import React, { FC, useMemo } from "react"; import React, { FC, useMemo } from "react";
import { useShallow } from "zustand/react/shallow";
import { NodeDef } from "../behavior3/src/behavior3"; import { NodeDef } from "../behavior3/src/behavior3";
import { useWorkspace } from "../contexts/workspace-context"; import { useWorkspace } from "../contexts/workspace-context";
import { Hotkey, isMacos } from "../misc/keys"; import { Hotkey, isMacos } from "../misc/keys";
@@ -15,17 +16,19 @@ interface OptionType {
} }
export const TitleBar: FC<LayoutProps> = () => { export const TitleBar: FC<LayoutProps> = () => {
const workspace = { const workspace = useWorkspace(
allFiles: useWorkspace((state) => state.allFiles), useShallow((state) => ({
fileTree: useWorkspace((state) => state.fileTree), allFiles: state.allFiles,
nodeDefs: useWorkspace((state) => state.nodeDefs), fileTree: state.fileTree,
isShowingSearch: useWorkspace((state) => state.isShowingSearch), nodeDefs: state.nodeDefs,
onShowingSearch: useWorkspace((state) => state.onShowingSearch), isShowingSearch: state.isShowingSearch,
onEditingNodeDef: useWorkspace((state) => state.onEditingNodeDef), onShowingSearch: state.onShowingSearch,
open: useWorkspace((state) => state.open), onEditingNodeDef: state.onEditingNodeDef,
name: useWorkspace((state) => state.path), open: state.open,
relative: useWorkspace((state) => state.relative), name: state.path,
}; relative: state.relative,
}))
);
const searchOptions = useMemo(() => { const searchOptions = useMemo(() => {
const options: OptionType[] = []; const options: OptionType[] = [];
workspace.allFiles.forEach((file) => { workspace.allFiles.forEach((file) => {
+19 -19
View File
@@ -8,6 +8,7 @@ import { PiTreeStructureFill } from "react-icons/pi";
import { VscNewFolder, VscRepo } from "react-icons/vsc"; import { VscNewFolder, VscRepo } from "react-icons/vsc";
import useForceUpdate from "use-force-update"; import useForceUpdate from "use-force-update";
import { useWindowSize } from "usehooks-ts"; import { useWindowSize } from "usehooks-ts";
import { useShallow } from "zustand/react/shallow";
import { useSetting } from "../contexts/setting-context"; import { useSetting } from "../contexts/setting-context";
import { EditorStore, useWorkspace } from "../contexts/workspace-context"; import { EditorStore, useWorkspace } from "../contexts/workspace-context";
import { modal } from "../misc/hooks"; import { modal } from "../misc/hooks";
@@ -21,25 +22,24 @@ import { TitleBar } from "./titlebar";
const { Header, Content, Sider } = Layout; const { Header, Content, Sider } = Layout;
export const Workspace: FC = () => { export const Workspace: FC = () => {
const workspace = { const workspace = useWorkspace(
buildProject: useWorkspace((state) => state.buildProject), useShallow((state) => ({
close: useWorkspace((state) => state.close), save: state.save,
createProject: useWorkspace((state) => state.createProject), editors: state.editors,
edit: useWorkspace((state) => state.edit), modifiedTime: state.modifiedTime,
editing: useWorkspace((state) => state.editing), isShowingSearch: state.isShowingSearch,
editors: useWorkspace((state) => state.editors), onShowingSearch: state.onShowingSearch,
fileTree: useWorkspace((state) => state.fileTree), openProject: state.openProject,
find: useWorkspace((state) => state.find), buildProject: state.buildProject,
init: useWorkspace((state) => state.init), close: state.close,
modifiedTime: useWorkspace((state) => state.modifiedTime), createProject: state.createProject,
isShowingSearch: useWorkspace((state) => state.isShowingSearch), edit: state.edit,
onShowingSearch: useWorkspace((state) => state.onShowingSearch), editing: state.editing,
openProject: useWorkspace((state) => state.openProject), fileTree: state.fileTree,
save: useWorkspace((state) => state.save), find: state.find,
}; }))
const settings = { );
recent: useSetting((state) => state.recent), const settings = useSetting(useShallow((state) => ({ recent: state.recent })));
};
const [isShowingAlert, setShowingAlert] = useState(false); const [isShowingAlert, setShowingAlert] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();