Kothing
Author of Kothing, a Bootstrap Medium styled template available for WordPress, HTML, Ghost and Jekyll. You are currently previewing Jekyll template demo.

React使用createContext的TypeScript写法

React createContext的TypeScript写法

React中使用createContext的TypeScript写法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// type.tsx
export enum ItemType {
  Reveal = 'REVEAL',
  Replay = 'REPLAY'
}

export enum ViewMode {
  View,
  Edit
}

export enum ItemStatus {
  Draft = 'DRAFT',
  Approval = 'APPROVAL',
  Approved = 'APPROVED',
  Done = 'DONE'
}
1
2
3
4
5
6
7
8
// constant.ts
import { ItemStatus } from './types';
export const ItemStatusConf: Record<ItemStatus, string> = {
  [ItemStatus.Draft]: '草稿',
  [ItemStatus.Approval]: '待审核',
  [ItemStatus.Approved]: '已审核',
  [ItemStatus.Done]: '已完成'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// context.tsx
import React, { createContext, Dispatch, SetStateAction, } from 'react';
import { FormInstance } from 'antd';
import { ItemType, ViewMode } from './types';

export const ItemContext = createContext<{
  id: number;
  type: ItemType;
  form: FormInstance<any>;
  status?: ItemStatus;
  viewMode: ViewMode;
  setViewMode: Dispatch<SetStateAction<ViewMode>>;
  forceUpdate?: () => void;
}>({} as any);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Child.tsx

import React, { useContext } from 'react';
import { Form, Radio } from 'antd';
import { ItemStatus } from './types';
import { ItemStatusConf } from './constant';
import { ItemContext } from './context.ts';

interface ChildProps {
}

const Child: React.FC<ChildProps> = () => {
  const { id, type, form, viewMode, setViewMode } = useContext(ItemContext);

  const [value, setValue] = useState<ItemStatus>(ItemStatus.Draft);

  const onChange = e => {
    console.log('radio checked', e.target.value);
    setValue(e.target.value);
  };

  return (
    <Form
      name="test_form"
      form={form}
    >
      <Form.Item name="status" label="状态">
        <Radio.Group onChange={onChange} value={value}>
          {Object.entries(ItemStatusConf).map(([status, text]) => (<Radio value={status}>{text}</Radio>))}
        </Radio.Group>
      </Form.Item>
    </Form>
  );
};

export default Child;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// App.tsx

import React, { useMemo } from 'react';
import { Form } from 'antd';
import { ItemType, ViewMode } from './types';
import { ItemStatusConf } from './constant';
import { ItemContext } from './context.ts';
import Child from './Child';

interface AppProps {
  id: number;
  type: ItemType;
}

const forceUpdate = () => {
  console.log('forceUpdate');
}

const App: React.FC<AppProps> = ({ id, type }) => {
  const initMode = !id ? ViewMode.Edit : ViewMode.View;
  const [viewMode, setViewMode] = useState<ViewMode>(initMode);
  const [form] = Form.useForm();

  const contextValue = useMemo(() => ({
    id,
    type,
    form,
    viewMode, 
    setViewMode,
    forceUpdate
  }), [id, type, viewMode, setViewMode, forceUpdate]);

  return (
    <ItemContext.Provider value={contextValue}>
      <Child/>
    </ItemContext.Provider>
  );
};

export default App;