From 06bd1470be4ab7b8ee6001fedca8cfaef4a02301 Mon Sep 17 00:00:00 2001 From: suanmei Date: Tue, 12 May 2020 10:54:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20useContext=20+=20useReducer=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/json-schema-editor/package-lock.json | 5 + packages/json-schema-editor/package.json | 3 +- .../src/{ace/index.tsx => components/ace.tsx} | 0 .../src/components/editor-head.tsx | 94 +++++++++++++++++++ .../src/components/layout.tsx | 28 ++++++ .../src/components/schema-form.tsx | 22 +++++ .../json-schema-editor/src/context/ui.tsx | 20 ++++ packages/json-schema-editor/src/i18n/index.ts | 1 + .../src/i18n/translations/en.json | 4 +- .../src/i18n/translations/zh.json | 4 +- packages/json-schema-editor/src/index.tsx | 77 ++------------- .../json-schema-editor/src/model/index.ts | 1 + packages/json-schema-editor/src/model/ui.ts | 13 +++ packages/json-schema-editor/src/reducer/ui.ts | 16 ++++ packages/json-schema-editor/src/store/ui.ts | 16 ++++ .../src/utils/schema-json.ts | 0 .../src/utils/styles/common.ts | 44 +++++++++ .../src/utils/styles/global.ts | 6 +- 18 files changed, 278 insertions(+), 76 deletions(-) rename packages/json-schema-editor/src/{ace/index.tsx => components/ace.tsx} (100%) create mode 100644 packages/json-schema-editor/src/components/editor-head.tsx create mode 100644 packages/json-schema-editor/src/components/layout.tsx create mode 100644 packages/json-schema-editor/src/components/schema-form.tsx create mode 100644 packages/json-schema-editor/src/context/ui.tsx create mode 100644 packages/json-schema-editor/src/model/index.ts create mode 100644 packages/json-schema-editor/src/model/ui.ts create mode 100644 packages/json-schema-editor/src/reducer/ui.ts create mode 100644 packages/json-schema-editor/src/store/ui.ts create mode 100644 packages/json-schema-editor/src/utils/schema-json.ts diff --git a/packages/json-schema-editor/package-lock.json b/packages/json-schema-editor/package-lock.json index 5ffb250..33be3f0 100644 --- a/packages/json-schema-editor/package-lock.json +++ b/packages/json-schema-editor/package-lock.json @@ -1199,6 +1199,11 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==", "dev": true }, + "react-tracked": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-tracked/-/react-tracked-1.3.0.tgz", + "integrity": "sha512-RRo2L+b+WsvBegXamRb6tfgdtdTXL/zOWvPV52yI8+yiiqZ+Zumakp4xasb1eVzPTW0Ow70DA0Rq40KS/4/j0g==" + }, "regenerator-runtime": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", diff --git a/packages/json-schema-editor/package.json b/packages/json-schema-editor/package.json index 7cdcfcf..b536058 100644 --- a/packages/json-schema-editor/package.json +++ b/packages/json-schema-editor/package.json @@ -58,6 +58,7 @@ "gitHead": "60b114ff262513544204f33a9bbcb6220d6c1c5d", "dependencies": { "i18next": "^19.4.4", - "react-i18next": "^11.4.0" + "react-i18next": "^11.4.0", + "react-tracked": "^1.3.0" } } diff --git a/packages/json-schema-editor/src/ace/index.tsx b/packages/json-schema-editor/src/components/ace.tsx similarity index 100% rename from packages/json-schema-editor/src/ace/index.tsx rename to packages/json-schema-editor/src/components/ace.tsx diff --git a/packages/json-schema-editor/src/components/editor-head.tsx b/packages/json-schema-editor/src/components/editor-head.tsx new file mode 100644 index 0000000..b4a42b0 --- /dev/null +++ b/packages/json-schema-editor/src/components/editor-head.tsx @@ -0,0 +1,94 @@ +/** @jsx jsx */ +import { jsx, css } from '@emotion/core'; +import styled from '@emotion/styled'; +import { Row, Col, Tooltip, Input, Checkbox, Select } from 'antd'; +import { useTranslation } from 'react-i18next'; +import { useUIState, useSetUIState } from '../store/ui'; +import { + CaretDownIcon, + CaretRightIcon, + EditIcon, + SettingIcon, + PlusIcon, +} from '../utils/styles/common'; + +const { Option } = Select; + +const FieldInput = styled(Input)` + .ant-input-group-addon { + background: transparent; + border: none; + } +`; + +function EditorHead(): JSX.Element { + const { t } = useTranslation(); + const uiState = useUIState(); + const setUIState = useSetUIState(); + const { formVisible } = uiState; + + const toggleFormVisible = (): void => { + setUIState((prev) => ({ ...prev, formVisible: !formVisible })); + }; + + return ( + + + + + + + {formVisible ? ( + + ) : ( + + )} + + + + { + // code + }} + /> + + } + /> + + + + + + + + } /> + + + } /> + + + + + + + + + + + + + ); +} + +export default EditorHead; diff --git a/packages/json-schema-editor/src/components/layout.tsx b/packages/json-schema-editor/src/components/layout.tsx new file mode 100644 index 0000000..83cf598 --- /dev/null +++ b/packages/json-schema-editor/src/components/layout.tsx @@ -0,0 +1,28 @@ +/** @jsx jsx */ +import { jsx, css } from '@emotion/core'; +import { Button } from 'antd'; +import { useTranslation } from 'react-i18next'; +import EditorHead from './editor-head'; +import SchemaForm from './schema-form'; +import { useUIState } from '../store/ui'; + +function Layout(): JSX.Element { + const { t } = useTranslation(); + const uiState = useUIState(); + const { formVisible } = uiState; + + return ( +
+ + + {formVisible && } +
+ ); +} + +export default Layout; diff --git a/packages/json-schema-editor/src/components/schema-form.tsx b/packages/json-schema-editor/src/components/schema-form.tsx new file mode 100644 index 0000000..26f82fd --- /dev/null +++ b/packages/json-schema-editor/src/components/schema-form.tsx @@ -0,0 +1,22 @@ +/** @jsx jsx */ +import { useEffect, memo, useRef } from 'react'; +import { jsx } from '@emotion/core'; +import { useUIState } from '../store/ui'; + +function SchemaForm(): JSX.Element { + const uiState = useUIState(); + const { formVisible } = uiState; + const renders = useRef(1); + useEffect(() => { + console.log(11111); + }); + renders.current += 1; + return ( +
+ {formVisible ? 3 : 0} + (renders:{renders.current}) +
+ ); +} + +export default memo(SchemaForm); diff --git a/packages/json-schema-editor/src/context/ui.tsx b/packages/json-schema-editor/src/context/ui.tsx new file mode 100644 index 0000000..af8bd0e --- /dev/null +++ b/packages/json-schema-editor/src/context/ui.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import { createContext, useContext, useReducer } from 'react'; +import uiReducer from '../reducer/ui'; +import { UIContext } from '../model'; + +interface ProviderProps { + children: React.ReactChild; +} + +const initialData = { formVisible: true, aaa: true }; + +const Context = createContext({ uiState: initialData } as UIContext); + +export const UIProvider = ({ children }: ProviderProps): JSX.Element => { + const [uiState, uiDispatch] = useReducer(uiReducer, initialData); + + return {children}; +}; + +export const useUI = (): UIContext => useContext(Context); diff --git a/packages/json-schema-editor/src/i18n/index.ts b/packages/json-schema-editor/src/i18n/index.ts index d8637b1..e05baa9 100644 --- a/packages/json-schema-editor/src/i18n/index.ts +++ b/packages/json-schema-editor/src/i18n/index.ts @@ -13,6 +13,7 @@ i18n 'en-US': en, 'zh-CN': zh, }, + lng: 'en', keySeparator: false, // we do not use keys in form messages.welcome interpolation: { escapeValue: false, // react already safes from xss diff --git a/packages/json-schema-editor/src/i18n/translations/en.json b/packages/json-schema-editor/src/i18n/translations/en.json index 3ad499d..efe7e44 100644 --- a/packages/json-schema-editor/src/i18n/translations/en.json +++ b/packages/json-schema-editor/src/i18n/translations/en.json @@ -1,6 +1,8 @@ { "translation": { "import_json": "Import JSON", - "select_all": "Select All" + "select_all": "Select All", + "setting": "Advanced Setting", + "add_child_node": "Add child node" } } diff --git a/packages/json-schema-editor/src/i18n/translations/zh.json b/packages/json-schema-editor/src/i18n/translations/zh.json index fcd7164..40a9e1b 100644 --- a/packages/json-schema-editor/src/i18n/translations/zh.json +++ b/packages/json-schema-editor/src/i18n/translations/zh.json @@ -1,6 +1,8 @@ { "translation": { "import_json": "导入 JSON", - "select_all": "全选" + "select_all": "全选", + "setting": "高级设置", + "add_child_node": "添加子节点" } } diff --git a/packages/json-schema-editor/src/index.tsx b/packages/json-schema-editor/src/index.tsx index 682ab09..32c0711 100644 --- a/packages/json-schema-editor/src/index.tsx +++ b/packages/json-schema-editor/src/index.tsx @@ -1,10 +1,9 @@ /** @jsx jsx */ import { useEffect } from 'react'; -import { Global, jsx, css } from '@emotion/core'; -import styled from '@emotion/styled'; -import { Row, Col, Tooltip, Input, Checkbox, Select, Button } from 'antd'; -import { CaretDownOutlined, EditOutlined, SettingOutlined, PlusOutlined } from '@ant-design/icons'; +import { Global, jsx } from '@emotion/core'; import { useTranslation } from 'react-i18next'; +import Layout from './components/layout'; +import { UIProvider } from './store/ui'; import globalStyles from './utils/styles/global'; import './i18n'; @@ -12,17 +11,8 @@ interface EditorProps { lang?: string; } -const { Option } = Select; - -const FieldInput = styled(Input)` - .ant-input-group-addon { - background: transparent; - border: none; - } -`; - function JsonSchemaEditor({ lang }: EditorProps): JSX.Element { - const { t, i18n } = useTranslation(); + const { i18n } = useTranslation(); useEffect(() => { if (!lang) return; @@ -30,63 +20,10 @@ function JsonSchemaEditor({ lang }: EditorProps): JSX.Element { }, [i18n, lang]); return ( -
+ - - - - - - - - - - - - { - // code - }} - /> - - } - /> - - - - - - - - } /> - - - } /> - - - - - - - - -
+ + ); } diff --git a/packages/json-schema-editor/src/model/index.ts b/packages/json-schema-editor/src/model/index.ts new file mode 100644 index 0000000..5ecdd1f --- /dev/null +++ b/packages/json-schema-editor/src/model/index.ts @@ -0,0 +1 @@ +export * from './ui'; diff --git a/packages/json-schema-editor/src/model/ui.ts b/packages/json-schema-editor/src/model/ui.ts new file mode 100644 index 0000000..f3cd2e2 --- /dev/null +++ b/packages/json-schema-editor/src/model/ui.ts @@ -0,0 +1,13 @@ +export interface UIState { + formVisible: boolean; + aaa: boolean; +} + +export interface UIAction { + type: string; +} + +export interface UIContext { + uiState: UIState; + uiDispatch: React.Dispatch; +} diff --git a/packages/json-schema-editor/src/reducer/ui.ts b/packages/json-schema-editor/src/reducer/ui.ts new file mode 100644 index 0000000..a660671 --- /dev/null +++ b/packages/json-schema-editor/src/reducer/ui.ts @@ -0,0 +1,16 @@ +import { UIState, UIAction } from '../model'; + +const reducer = (state: UIState, action: UIAction): UIState => { + switch (action.type) { + case 'TOGGLE_FORM_VISIBLE': + return { formVisible: state.formVisible, aaa: false }; + case 'increment': + return state; + case 'decrement': + return state; + default: + return state; + } +}; + +export default reducer; diff --git a/packages/json-schema-editor/src/store/ui.ts b/packages/json-schema-editor/src/store/ui.ts new file mode 100644 index 0000000..5731067 --- /dev/null +++ b/packages/json-schema-editor/src/store/ui.ts @@ -0,0 +1,16 @@ +import { useState, Dispatch, SetStateAction } from 'react'; +import { createContainer } from 'react-tracked'; + +export type State = { + formVisible: boolean; +}; + +const initialData = { formVisible: true }; + +const useValue = (): [State, Dispatch>] => useState(initialData); + +export const { + Provider: UIProvider, + useTrackedState: useUIState, + useUpdate: useSetUIState, +} = createContainer(useValue); diff --git a/packages/json-schema-editor/src/utils/schema-json.ts b/packages/json-schema-editor/src/utils/schema-json.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/json-schema-editor/src/utils/styles/common.ts b/packages/json-schema-editor/src/utils/styles/common.ts index e69de29..75d7ae0 100644 --- a/packages/json-schema-editor/src/utils/styles/common.ts +++ b/packages/json-schema-editor/src/utils/styles/common.ts @@ -0,0 +1,44 @@ +import { css } from '@emotion/core'; +import styled from '@emotion/styled'; +import { + CaretDownOutlined, + CaretRightOutlined, + EditOutlined, + SettingOutlined, + PlusOutlined, +} from '@ant-design/icons'; + +const cursorStyle = css` + cursor: pointer; +`; + +const IconStyle = css` + margin: 0 5px; + svg { + font-size: 14px; + } +`; + +export const CaretDownIcon = styled(CaretDownOutlined)` + ${cursorStyle} +`; + +export const CaretRightIcon = styled(CaretRightOutlined)` + ${cursorStyle} +`; + +export const EditIcon = styled(EditOutlined)` + ${cursorStyle} +`; + +export const SettingIcon = styled(SettingOutlined)` + color: #00a854; + ${cursorStyle} + ${IconStyle} +`; + +export const PlusIcon = styled(PlusOutlined)` + color: #2395f1; + ${cursorStyle} + ${IconStyle} +`; diff --git a/packages/json-schema-editor/src/utils/styles/global.ts b/packages/json-schema-editor/src/utils/styles/global.ts index 9876c5e..48d4ce2 100644 --- a/packages/json-schema-editor/src/utils/styles/global.ts +++ b/packages/json-schema-editor/src/utils/styles/global.ts @@ -7,12 +7,12 @@ const globalStyles = css` } .ant-col { - :nth-child(2) { + :nth-of-type(2) { text-align: center; } - :nth-child(3), - :nth-child(4) { + :nth-of-type(3), + :nth-of-type(4) { padding-right: 10px; } }