Browse Source

feat: useContext + useReducer 实现状态管理

master
suanmei 5 years ago
committed by 拾邑
parent
commit
06bd1470be
  1. 5
      packages/json-schema-editor/package-lock.json
  2. 3
      packages/json-schema-editor/package.json
  3. 0
      packages/json-schema-editor/src/components/ace.tsx
  4. 94
      packages/json-schema-editor/src/components/editor-head.tsx
  5. 28
      packages/json-schema-editor/src/components/layout.tsx
  6. 22
      packages/json-schema-editor/src/components/schema-form.tsx
  7. 20
      packages/json-schema-editor/src/context/ui.tsx
  8. 1
      packages/json-schema-editor/src/i18n/index.ts
  9. 4
      packages/json-schema-editor/src/i18n/translations/en.json
  10. 4
      packages/json-schema-editor/src/i18n/translations/zh.json
  11. 77
      packages/json-schema-editor/src/index.tsx
  12. 1
      packages/json-schema-editor/src/model/index.ts
  13. 13
      packages/json-schema-editor/src/model/ui.ts
  14. 16
      packages/json-schema-editor/src/reducer/ui.ts
  15. 16
      packages/json-schema-editor/src/store/ui.ts
  16. 0
      packages/json-schema-editor/src/utils/schema-json.ts
  17. 44
      packages/json-schema-editor/src/utils/styles/common.ts
  18. 6
      packages/json-schema-editor/src/utils/styles/global.ts

5
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",

3
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"
}
}

0
packages/json-schema-editor/src/ace/index.tsx → packages/json-schema-editor/src/components/ace.tsx

94
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 (
<Row
css={css`
margin-top: 10px;
`}
>
<Col span="24">
<Row align="middle">
<Col span="8">
<Row align="middle">
<Col span="2">
{formVisible ? (
<CaretDownIcon onClick={toggleFormVisible} />
) : (
<CaretRightIcon onClick={toggleFormVisible} />
)}
</Col>
<Col span="22">
<FieldInput
disabled
value="root"
addonAfter={
<Tooltip placement="top" title={t('select_all')}>
<Checkbox
checked={false}
onChange={(): void => {
// code
}}
/>
</Tooltip>
}
/>
</Col>
</Row>
</Col>
<Col span="3">
<Select value="object" disabled>
<Option value="object">object</Option>
</Select>
</Col>
<Col span="5">
<Input value="" placeholder="Title" addonAfter={<EditIcon />} />
</Col>
<Col span="5">
<Input value="" placeholder="Description" addonAfter={<EditIcon />} />
</Col>
<Col span="3">
<Tooltip placement="top" title={t('setting')}>
<SettingIcon />
</Tooltip>
<Tooltip placement="top" title={t('add_child_node')}>
<PlusIcon />
</Tooltip>
</Col>
</Row>
</Col>
</Row>
);
}
export default EditorHead;

28
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 (
<div
className="json-schema-editor"
css={css`
padding: 5px;
`}
>
<Button type="primary">{t('import_json')}</Button>
<EditorHead />
{formVisible && <SchemaForm />}
</div>
);
}
export default Layout;

22
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 (
<div>
{formVisible ? 3 : 0}
(renders:{renders.current})
</div>
);
}
export default memo(SchemaForm);

20
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 <Context.Provider value={{ uiState, uiDispatch }}>{children}</Context.Provider>;
};
export const useUI = (): UIContext => useContext(Context);

1
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

4
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"
}
}

4
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": "添加子节点"
}
}

77
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 (
<div
className="json-schema-editor"
css={css`
padding: 5px;
`}
>
<UIProvider>
<Global styles={globalStyles} />
<Button type="primary">{t('import_json')}</Button>
<Row
css={css`
margin-top: 10px;
`}
>
<Col span="24">
<Row align="middle">
<Col span="8">
<Row align="middle">
<Col span="2">
<CaretDownOutlined className="editor-icon" />
</Col>
<Col span="22">
<FieldInput
disabled
value="root"
addonAfter={
<Tooltip placement="top" title={t('select_all')}>
<Checkbox
checked={false}
onChange={(): void => {
// code
}}
/>
</Tooltip>
}
/>
</Col>
</Row>
</Col>
<Col span="3">
<Select value="object" disabled>
<Option value="object">object</Option>
</Select>
</Col>
<Col span="5">
<Input value="" placeholder="Title" addonAfter={<EditOutlined />} />
</Col>
<Col span="5">
<Input value="" placeholder="Description" addonAfter={<EditOutlined />} />
</Col>
<Col span="3">
<SettingOutlined className="editor-icon" style={{ color: '#00a854' }} />
<PlusOutlined className="editor-icon" style={{ color: '#2395f1' }} />
</Col>
</Row>
</Col>
</Row>
</div>
<Layout />
</UIProvider>
);
}

1
packages/json-schema-editor/src/model/index.ts

@ -0,0 +1 @@
export * from './ui';

13
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<UIAction>;
}

16
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;

16
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<SetStateAction<State>>] => useState<State>(initialData);
export const {
Provider: UIProvider,
useTrackedState: useUIState,
useUpdate: useSetUIState,
} = createContainer(useValue);

0
packages/json-schema-editor/src/utils/schema-json.ts

44
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}
`;

6
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;
}
}

Loading…
Cancel
Save