Browse Source

修复IconPicker为空的时候,会无限刷新组件

main
dark 5 months ago
parent
commit
b74edf100c
  1. 11
      src/components/icon/action/ActionIcon.tsx
  2. 10
      src/components/icon/picker/context.tsx
  3. 24
      src/components/icon/picker/index.tsx
  4. 5
      src/pages/system/menus/index.tsx

11
src/components/icon/action/ActionIcon.tsx

@ -1,6 +1,6 @@
import type { ButtonProps, TooltipProps } from 'antd'
import { Button, Tooltip } from 'antd'
import type { CSSProperties, FC } from 'react'
import { CSSProperties, FC, memo } from 'react'
import { ConfigProvider } from '@/components/config-provider'
import { useStyles } from './style'
@ -47,7 +47,7 @@ export interface ActionIconProps extends Omit<ButtonProps, 'title' | 'size'> {
bordered?: boolean;
}
const BaseActionIcon: FC<ActionIconProps> = ({
const BaseActionIcon: FC<ActionIconProps> = memo(({
placement,
title,
icon,
@ -91,9 +91,9 @@ const BaseActionIcon: FC<ActionIconProps> = ({
)}
</>
)
}
})
const ActionIcon = (props: ActionIconProps) => {
const ActionIcon = memo((props: ActionIconProps) => {
const { size } = props || {}
const { theme: token } = useStyles({ size })
@ -110,5 +110,6 @@ const ActionIcon = (props: ActionIconProps) => {
<BaseActionIcon {...props} />
</ConfigProvider>
)
}
})
export default ActionIcon

10
src/components/icon/picker/context.tsx

@ -2,11 +2,13 @@ import { IconUnit, ReactIcon } from '../types.ts'
import { antdIconList, parkIconList } from './icons.ts'
import { createContext, ProviderProps, useContext, useReducer, useMemo, useCallback } from 'react'
export const ICON_RESET = Symbol.for('ICON_RESET')
export interface State {
/**
* @title
*/
icon?: IconUnit;
icon?: IconUnit | typeof ICON_RESET ;
/**
* @title
*/
@ -80,11 +82,12 @@ type Actions = {
isEmptyIconParkList: boolean;
}
// 创建reducer函数
const reducer = (state: State, action: Action) => {
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'resetIcon':
return { ...state, icon: undefined }
return { ...state, icon: ICON_RESET }
case 'togglePanel':
return { ...state, open: action.payload ?? !state.open }
case 'selectIcon':
@ -100,6 +103,7 @@ const reducer = (state: State, action: Action) => {
}
}
export const PickerContextProvider = ({ value: propValue, children }: ProviderProps<ContextValue>) => {
const [ state, dispatch ] = useReducer(reducer, {

24
src/components/icon/picker/index.tsx

@ -1,23 +1,27 @@
import { Popover, PopoverProps } from 'antd'
import { FC, useEffect } from 'react'
import { FC, memo, useEffect } from 'react'
import Display from './Display.tsx'
import PickerPanel from './PickerPanel'
import { PickerContextProvider, usePickerContext } from './context.tsx'
import { ICON_RESET, PickerContextProvider, usePickerContext } from './context.tsx'
import { IconUnit } from '@/components/icon/types.ts'
interface PickerProps extends Partial<PopoverProps> {
value?: string,
onChange?: (value: string) => void,
}
const IconPicker: FC = (props: PickerProps) => {
const IconPicker: FC = memo((props: PickerProps) => {
const { state, actions: { selectIcon, togglePanel } } = usePickerContext()
const { value, onChange } = props
useEffect(() => {
if (onChange) {
onChange(state.icon ? `${state.icon.type}:${state.icon.componentName}` : '')
if (onChange && state.icon) {
if (state.icon === ICON_RESET) {
return onChange('')
}
const icon = state.icon as IconUnit
onChange(state.icon ? `${icon.type}:${icon.componentName}` : '')
}
}, [ state.icon ])
@ -26,7 +30,7 @@ const IconPicker: FC = (props: PickerProps) => {
if (value) {
const [ type, componentName ] = value.split(':')
selectIcon({ type, componentName } as any)
}else{
} else {
selectIcon(null as any)
}
}, [ value ])
@ -47,10 +51,10 @@ const IconPicker: FC = (props: PickerProps) => {
<Display/>
</Popover>
)
}
})
export default (props: PickerProps) => {
export default memo((props: PickerProps) => {
return <PickerContextProvider value={{} as any}>
<IconPicker {...props as any}/>
</PickerContextProvider>
}
})

5
src/pages/system/menus/index.tsx

@ -151,7 +151,10 @@ const Menus = () => {
label={t('system.menus.form.name', '别名')} name={'name'}>
<Input placeholder={t('system.menus.form.name', '别名')}/>
</Form.Item>
<Form.Item label={t('system.menus.form.icon', '图标')} name={'icon'}>
<Form.Item label={t('system.menus.form.icon', '图标')} name={'icon'}
shouldUpdate={(prev: any, next: any) => {
return prev.icon !== next.icon
}}>
<IconPicker placement={'left'}/>
</Form.Item>
<Form.Item label={t('system.menus.form.sort', '排序')} name={'sort'}>

Loading…
Cancel
Save