mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-27 08:39:59 +08:00
fix: make the value of mergeState up-to-date & fix ref reference error
This commit is contained in:
parent
093abf0108
commit
b3a2d62f8a
@ -39,8 +39,8 @@ const options = {
|
||||
};
|
||||
|
||||
export const Alert = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, ...cProps } = getComponentProps(props);
|
||||
const { customStyle, slotsElements, callbackMap } = props;
|
||||
const { ...cProps } = getComponentProps(props);
|
||||
const { elementRef, customStyle, slotsElements, callbackMap } = props;
|
||||
|
||||
return (
|
||||
<BaseAlert
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
CascaderPropsSpec as BaseCascaderPropsSpec,
|
||||
CascaderValueSpec,
|
||||
} from '../generated/types/Cascader';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import { isArray } from 'lodash-es';
|
||||
import { SelectViewHandle } from '@arco-design/web-react/es/_class/select-view';
|
||||
|
||||
@ -108,9 +108,9 @@ const options = {
|
||||
};
|
||||
|
||||
export const Cascader = implementRuntimeComponent(options)(props => {
|
||||
const { getElement, callbackMap, multiple, placeholder, ...cProps } =
|
||||
getComponentProps(props);
|
||||
const { mergeState, slotsElements, customStyle, options } = props;
|
||||
const { getElement, callbackMap, mergeState, slotsElements, customStyle } = props;
|
||||
|
||||
const { multiple, options, placeholder, ...cProps } = getComponentProps(props);
|
||||
const ref = useRef<SelectViewHandle | null>(null);
|
||||
|
||||
const content = isArray(slotsElements.content)
|
||||
@ -124,18 +124,14 @@ export const Cascader = implementRuntimeComponent(options)(props => {
|
||||
defaultValue = [cProps.defaultValue as string[]];
|
||||
}
|
||||
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
const [value, setValue] = useState<string[] | string[][]>(defaultValue);
|
||||
|
||||
// optimize the display when switching from single selection to multiple selection
|
||||
useEffect(() => {
|
||||
const convertValue = useMemo(() => {
|
||||
if (mode === 'multiple' && !Array.isArray(value[0])) {
|
||||
setValue([value as string[]]);
|
||||
return [value as string[]];
|
||||
}
|
||||
}, [mode]);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({ value });
|
||||
}, [value, mergeState]);
|
||||
return value;
|
||||
}, [value, mode]);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
@ -144,10 +140,14 @@ export const Cascader = implementRuntimeComponent(options)(props => {
|
||||
}
|
||||
}, [getElement, ref]);
|
||||
|
||||
const onChange = (value: (string | string[])[]) => {
|
||||
setValue(value);
|
||||
callbackMap?.onChange?.();
|
||||
};
|
||||
const onChange = useCallback(
|
||||
(value: string[] | string[][]) => {
|
||||
setValue(value);
|
||||
mergeState({ value });
|
||||
callbackMap?.onChange?.();
|
||||
},
|
||||
[mergeState, callbackMap]
|
||||
);
|
||||
|
||||
return (
|
||||
<BaseCascader
|
||||
@ -155,8 +155,8 @@ export const Cascader = implementRuntimeComponent(options)(props => {
|
||||
className={css(customStyle?.content)}
|
||||
{...cProps}
|
||||
mode={mode}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
onChange={onChange as ((value: (string | string[])[]) => void) | undefined}
|
||||
value={convertValue}
|
||||
options={convertArrToTree(options)}
|
||||
placeholder={placeholder}
|
||||
>
|
||||
|
@ -4,7 +4,7 @@ import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { CollapsePropsSpec as BaseCollapsePropsSpec } from '../generated/types/Collapse';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { EmptyPlaceholder } from './_internal/EmptyPlaceholder';
|
||||
|
||||
const CollapsePropsSpec = Type.Object(BaseCollapsePropsSpec);
|
||||
@ -61,14 +61,14 @@ export const Collapse = implementRuntimeComponent(options)(props => {
|
||||
|
||||
const [activeKey, setActiveKey] = useState<string[]>(defaultActiveKey.map(String));
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({ activeKey });
|
||||
}, [activeKey, mergeState]);
|
||||
|
||||
const onChange = (currentOperateKey: string, activeKey: string[]) => {
|
||||
setActiveKey(activeKey);
|
||||
callbackMap?.onChange?.();
|
||||
};
|
||||
const onChange = useCallback(
|
||||
(currentOperateKey: string, activeKey: string[]) => {
|
||||
setActiveKey(activeKey);
|
||||
mergeState({ activeKey });
|
||||
callbackMap?.onChange?.();
|
||||
},
|
||||
[callbackMap, mergeState]
|
||||
);
|
||||
|
||||
const collapseItems = slotsElements.content
|
||||
? ([] as React.ReactElement[]).concat(slotsElements.content)
|
||||
|
@ -4,7 +4,7 @@ import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { InputPropsSpec as BaseInputPropsSpec } from '../generated/types/Input';
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useEffect, useState, useRef, useCallback } from 'react';
|
||||
import { RefInputType } from '@arco-design/web-react/es/Input/interface';
|
||||
|
||||
const InputPropsSpec = Type.Object({
|
||||
@ -50,11 +50,6 @@ export const Input = implementRuntimeComponent(options)(props => {
|
||||
const { defaultValue, ...cProps } = getComponentProps(props);
|
||||
const ref = useRef<RefInputType | null>(null);
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
}, [mergeState, value]);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
@ -63,6 +58,15 @@ export const Input = implementRuntimeComponent(options)(props => {
|
||||
}
|
||||
}, [getElement, ref]);
|
||||
|
||||
const onChange = useCallback(
|
||||
value => {
|
||||
setValue(value);
|
||||
mergeState({ value });
|
||||
callbackMap?.onChange?.();
|
||||
},
|
||||
[mergeState, callbackMap]
|
||||
);
|
||||
|
||||
return (
|
||||
<BaseInput
|
||||
className={css(customStyle?.input)}
|
||||
@ -72,18 +76,19 @@ export const Input = implementRuntimeComponent(options)(props => {
|
||||
prefix={slotsElements.prefix}
|
||||
suffix={slotsElements.suffix}
|
||||
value={value}
|
||||
onChange={value => {
|
||||
setValue(value);
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
onChange={onChange}
|
||||
onClear={() => {
|
||||
callbackMap?.onClear?.();
|
||||
}}
|
||||
onPressEnter={() => {
|
||||
callbackMap?.onPressEnter?.();
|
||||
}}
|
||||
onBlur={() => callbackMap?.onBlur?.()}
|
||||
onFocus={() => callbackMap?.onFocus?.()}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
{...cProps}
|
||||
/>
|
||||
);
|
||||
|
@ -38,8 +38,8 @@ const options = {
|
||||
};
|
||||
|
||||
export const Link = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, content, status, ...cProps } = getComponentProps(props);
|
||||
const { customStyle } = props;
|
||||
const { content, status, ...cProps } = getComponentProps(props);
|
||||
const { elementRef, customStyle } = props;
|
||||
|
||||
return (
|
||||
<BaseLink
|
||||
|
@ -4,7 +4,7 @@ import { css } from '@emotion/css';
|
||||
import { Type, Static } from '@sinclair/typebox';
|
||||
import { FALLBACK_METADATA, getComponentProps } from '../sunmao-helper';
|
||||
import { MentionsPropsSpec as BaseMentionsPropsSpec } from '../generated/types/Mentions';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
const MentionsPropsSpec = Type.Object(BaseMentionsPropsSpec);
|
||||
const MentionsStateSpec = Type.Object({
|
||||
@ -42,36 +42,36 @@ const options = {
|
||||
};
|
||||
|
||||
export const Mentions = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, defaultValue, ...cProps } = getComponentProps(props);
|
||||
const { mergeState, customStyle, callbackMap } = props;
|
||||
const { defaultValue, ...cProps } = getComponentProps(props);
|
||||
const { elementRef, mergeState, customStyle, callbackMap } = props;
|
||||
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({ value });
|
||||
}, [mergeState, value]);
|
||||
|
||||
const onChange = (value: string) => {
|
||||
setValue(value);
|
||||
callbackMap?.onChange?.();
|
||||
};
|
||||
|
||||
const onClear = () => {
|
||||
callbackMap?.onClear?.();
|
||||
};
|
||||
|
||||
const onPressEnter = () => {
|
||||
callbackMap?.onPressEnter?.();
|
||||
};
|
||||
const onChange = useCallback(
|
||||
(value: string) => {
|
||||
setValue(value);
|
||||
mergeState({ value });
|
||||
callbackMap?.onChange?.();
|
||||
},
|
||||
[callbackMap, mergeState]
|
||||
);
|
||||
|
||||
return (
|
||||
<BaseMentions
|
||||
ref={elementRef}
|
||||
onPressEnter={onPressEnter}
|
||||
onClear={onClear}
|
||||
onPressEnter={() => {
|
||||
callbackMap?.onPressEnter?.();
|
||||
}}
|
||||
onClear={() => {
|
||||
callbackMap?.onClear?.();
|
||||
}}
|
||||
className={css(customStyle?.content)}
|
||||
onBlur={() => callbackMap?.onBlur?.()}
|
||||
onFocus={() => callbackMap?.onFocus?.()}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
onChange={onChange}
|
||||
{...cProps}
|
||||
value={value}
|
||||
|
@ -23,7 +23,7 @@ const exampleProperties: Static<typeof MenuPropsSpec> = {
|
||||
{ key: 'key1', text: 'item1' },
|
||||
{ key: 'key2', text: 'item2' },
|
||||
],
|
||||
ellipsis:false,
|
||||
ellipsis: false,
|
||||
defaultActiveKey: 'key1',
|
||||
};
|
||||
|
||||
@ -38,29 +38,43 @@ export const Menu = implementRuntimeComponent({
|
||||
spec: {
|
||||
properties: MenuPropsSpec,
|
||||
state: MenuStateSpec,
|
||||
methods: {},
|
||||
methods: {
|
||||
setActive: Type.Object({
|
||||
active: Type.String(),
|
||||
}),
|
||||
},
|
||||
slots: [],
|
||||
styleSlots: ['content'],
|
||||
events: ['onClick'],
|
||||
},
|
||||
})(props => {
|
||||
const { elementRef, customStyle, callbackMap, mergeState } = props;
|
||||
const { elementRef, customStyle, callbackMap, mergeState, subscribeMethods } = props;
|
||||
const { items = [], defaultActiveKey, ...cProps } = getComponentProps(props);
|
||||
const [activeKey, setActiveKey] = useState<string>(defaultActiveKey);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
activeKey,
|
||||
setActiveKey(defaultActiveKey ?? 0);
|
||||
}, [defaultActiveKey]);
|
||||
|
||||
useEffect(() => {
|
||||
subscribeMethods({
|
||||
setActive: ({ active }) => {
|
||||
setActiveKey(active);
|
||||
mergeState({ activeKey: active });
|
||||
},
|
||||
});
|
||||
}, [activeKey, mergeState]);
|
||||
}, [subscribeMethods]);
|
||||
|
||||
return (
|
||||
<BaseMenu
|
||||
ref={elementRef}
|
||||
defaultSelectedKeys={[defaultActiveKey]}
|
||||
selectedKeys={[activeKey]}
|
||||
className={css(customStyle?.content)}
|
||||
onClickMenuItem={key => {
|
||||
setActiveKey(key);
|
||||
mergeState({
|
||||
activeKey: key,
|
||||
});
|
||||
callbackMap?.onClick?.();
|
||||
}}
|
||||
{...cProps}
|
||||
|
@ -44,8 +44,8 @@ export const Modal = implementRuntimeComponent({
|
||||
events: ['afterOpen', 'afterClose', 'onCancel', 'onOk'],
|
||||
},
|
||||
})(props => {
|
||||
const { subscribeMethods, slotsElements, customStyle, callbackMap } = props;
|
||||
const { getElement, title, defaultOpen, ...cProps } = getComponentProps(props);
|
||||
const { getElement, subscribeMethods, slotsElements, customStyle, callbackMap } = props;
|
||||
const { title, defaultOpen, ...cProps } = getComponentProps(props);
|
||||
const [visible, setVisible] = useState(defaultOpen);
|
||||
const contentRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
|
@ -46,8 +46,8 @@ const options = {
|
||||
};
|
||||
|
||||
export const Pagination = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, defaultCurrent, ...cProps } = getComponentProps(props);
|
||||
const { customStyle, mergeState, callbackMap } = props;
|
||||
const { defaultCurrent, ...cProps } = getComponentProps(props);
|
||||
const { elementRef, customStyle, mergeState, callbackMap } = props;
|
||||
|
||||
const [current, setCurrent] = useState<number>(defaultCurrent || 0);
|
||||
|
||||
@ -61,7 +61,7 @@ export const Pagination = implementRuntimeComponent(options)(props => {
|
||||
|
||||
const handleChange = (pageNum: number) => {
|
||||
setCurrent(pageNum);
|
||||
mergeState({ currentPage: current });
|
||||
mergeState({ currentPage: pageNum });
|
||||
callbackMap?.onChange?.();
|
||||
};
|
||||
|
||||
|
@ -51,12 +51,6 @@ export const PasswordInput = implementRuntimeComponent(options)(props => {
|
||||
const [value, setValue] = useState('');
|
||||
const ref = useRef<RefInputType | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
if (getElement && ele) {
|
||||
@ -71,10 +65,17 @@ export const PasswordInput = implementRuntimeComponent(options)(props => {
|
||||
value={value}
|
||||
onChange={value => {
|
||||
setValue(value);
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
onBlur={() => callbackMap?.onBlur?.()}
|
||||
onFocus={() => callbackMap?.onFocus?.()}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
onPressEnter={() => {
|
||||
callbackMap?.onPressEnter?.();
|
||||
}}
|
||||
|
@ -51,8 +51,8 @@ const options = {
|
||||
};
|
||||
|
||||
export const Radio = implementRuntimeComponent(options)(props => {
|
||||
const { customStyle, callbackMap, mergeState, subscribeMethods } = props;
|
||||
const { defaultCheckedValue, elementRef, ...cProps } = getComponentProps(props);
|
||||
const { customStyle, callbackMap, mergeState, subscribeMethods, elementRef } = props;
|
||||
const { defaultCheckedValue, ...cProps } = getComponentProps(props);
|
||||
const [checkedValue, setCheckedValue] = useState<string>('');
|
||||
const [isInit, setIsInit] = useState(false);
|
||||
|
||||
|
@ -32,7 +32,7 @@ const exampleProperties: Static<typeof SelectPropsSpec> = {
|
||||
],
|
||||
placeholder: 'Please select',
|
||||
size: 'default',
|
||||
error:false
|
||||
error: false,
|
||||
};
|
||||
|
||||
export const Select = implementRuntimeComponent({
|
||||
@ -66,11 +66,7 @@ export const Select = implementRuntimeComponent({
|
||||
const { options = [], retainInputValue, ...cProps } = getComponentProps(props);
|
||||
const [value, setValue] = useState<string>(defaultValue);
|
||||
const ref = useRef<SelectHandle | null>(null);
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
}, [mergeState, value]);
|
||||
|
||||
useEffect(() => {
|
||||
const ele = ref.current?.dom;
|
||||
if (getElement && ele) {
|
||||
@ -89,6 +85,9 @@ export const Select = implementRuntimeComponent({
|
||||
className={css(customStyle?.content)}
|
||||
onChange={v => {
|
||||
setValue(v);
|
||||
mergeState({
|
||||
value:v,
|
||||
});
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
value={value}
|
||||
@ -106,8 +105,12 @@ export const Select = implementRuntimeComponent({
|
||||
onClear={() => {
|
||||
callbackMap?.onClear?.();
|
||||
}}
|
||||
onBlur={() => callbackMap?.onBlur?.()}
|
||||
onFocus={() => callbackMap?.onFocus?.()}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
>
|
||||
{options.map(o => (
|
||||
<BaseSelect.Option key={o.value} value={o.value} disabled={o.disabled}>
|
||||
|
@ -37,8 +37,8 @@ const options = {
|
||||
};
|
||||
|
||||
export const Skeleton = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, ...cProps } = getComponentProps(props);
|
||||
const { customStyle, slotsElements } = props;
|
||||
const { ...cProps } = getComponentProps(props);
|
||||
const { elementRef, customStyle, slotsElements } = props;
|
||||
|
||||
return (
|
||||
<BaseSkeleton ref={elementRef} className={css(customStyle?.content)} {...cProps}>
|
||||
|
@ -38,21 +38,15 @@ const options = {
|
||||
methods: {},
|
||||
slots: [],
|
||||
styleSlots: ['content'],
|
||||
events: [],
|
||||
events: ['onChange'],
|
||||
},
|
||||
};
|
||||
|
||||
export const Switch = implementRuntimeComponent(options)(props => {
|
||||
const { elementRef, customStyle, mergeState } = props;
|
||||
const { elementRef, customStyle, mergeState, callbackMap } = props;
|
||||
const { defaultChecked, ...cProps } = getComponentProps(props);
|
||||
const [value, setValue] = useState<boolean>(defaultChecked);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
}, [value, mergeState]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(defaultChecked);
|
||||
}, [defaultChecked]);
|
||||
@ -63,7 +57,11 @@ export const Switch = implementRuntimeComponent(options)(props => {
|
||||
className={css(customStyle?.content)}
|
||||
checked={value}
|
||||
{...cProps}
|
||||
onChange={value => setValue(value)}
|
||||
onChange={value => {
|
||||
setValue(value);
|
||||
mergeState({ value });
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -60,12 +60,6 @@ export const TextArea = implementRuntimeComponent(options)(props => {
|
||||
}
|
||||
}, [getElement, ref]);
|
||||
|
||||
useEffect(() => {
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<BaseTextArea
|
||||
ref={ref}
|
||||
@ -73,13 +67,20 @@ export const TextArea = implementRuntimeComponent(options)(props => {
|
||||
value={value}
|
||||
onChange={value => {
|
||||
setValue(value);
|
||||
mergeState({
|
||||
value,
|
||||
});
|
||||
callbackMap?.onChange?.();
|
||||
}}
|
||||
onClear={() => {
|
||||
callbackMap?.onClear?.();
|
||||
}}
|
||||
onBlur={() => callbackMap?.onBlur?.()}
|
||||
onFocus={() => callbackMap?.onFocus?.()}
|
||||
onBlur={() => {
|
||||
callbackMap?.onBlur?.();
|
||||
}}
|
||||
onFocus={() => {
|
||||
callbackMap?.onFocus?.();
|
||||
}}
|
||||
onPressEnter={() => {
|
||||
callbackMap?.onPressEnter?.();
|
||||
}}
|
||||
|
@ -2,14 +2,11 @@ import { Type } from '@sinclair/typebox';
|
||||
import { StringUnion } from '../../sunmao-helper';
|
||||
import { Category } from '../../constants/category';
|
||||
|
||||
export const CascaderValueSpec = Type.Array(
|
||||
Type.Union([Type.String(), Type.Array(Type.String())]),
|
||||
{
|
||||
title: 'Default Value',
|
||||
category: Category.Data,
|
||||
widget: 'core/v1/expression',
|
||||
}
|
||||
);
|
||||
export const CascaderValueSpec = Type.Union([Type.Array(Type.String()), Type.Array(Type.Array(Type.String()))], {
|
||||
title: 'Default Value',
|
||||
category: Category.Data,
|
||||
widget: 'core/v1/expression',
|
||||
});
|
||||
|
||||
export const CascaderPropsSpec = {
|
||||
options: Type.Array(Type.Array(Type.String()), {
|
||||
|
@ -39,7 +39,7 @@ export const getComponentProps = <
|
||||
KEvent extends string
|
||||
>(
|
||||
props: T & ComponentImplProps<TState, TMethods, KSlot, KStyleSlot, KEvent>
|
||||
): T => {
|
||||
) => {
|
||||
const {
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
component,
|
||||
@ -59,5 +59,5 @@ export const getComponentProps = <
|
||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||
...rest
|
||||
} = props;
|
||||
return rest as unknown as T;
|
||||
return rest;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user