most react hooks updated

This commit is contained in:
Michael Peters 2022-02-07 01:09:38 -06:00
parent 434bc6bfe5
commit e002b7092c
16 changed files with 36 additions and 28 deletions

View File

@ -6,12 +6,13 @@ module.exports = {
plugins: [
'@typescript-eslint',
'unused-imports',
'react',
'react-hooks',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
],
settings: {
react: {
@ -159,6 +160,9 @@ module.exports = {
'react/jsx-props-no-multi-spaces': 'warn',
'react/jsx-props-no-spreading': 'error',
'react/jsx-tag-spacing': [ 'warn', { closingSlash: 'never', beforeSelfClosing: 'always', afterOpening: 'never', beforeClosing: 'never' } ],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
};

View File

@ -102,7 +102,7 @@ const DownloadButton: FC<DownloadButtonProps> = (props: DownloadButtonProps) =>
setButtonText('Reveal in Explorer');
setDownloading(false);
}, [ downloading, buttonShaking, downloadPath, downloadBuff ]);
}, [ guild, resourceId, resourceName, downloading, buttonShaking, downloadPath, downloadBuff ]);
return <Button shaking={buttonShaking} onClick={downloadListener}>{buttonText}</Button>;
};

View File

@ -18,7 +18,7 @@ const ChoicesControl: FC<ChoicesControlProps> = (props: ChoicesControlProps) =>
>
{choice.display}
</div>
)), [ choices, selectedId ]);
)), [ choices, selectedId, setSelectedId ]);
return (
<div className="choices-react">

View File

@ -45,11 +45,11 @@ const Display: FC<DisplayProps> = (props: DisplayProps) => {
}
}, [ saving, saveFailed ]);
const popup = useMemo(() => {
const dismissInfoMessage = () => {
setDismissedInfoMessage(infoMessage);
};
const popup = useMemo(() => {
if (errorMessage) {
return (
<DisplayPopup tip={errorMessage}>
@ -72,7 +72,7 @@ const Display: FC<DisplayProps> = (props: DisplayProps) => {
} else {
return null;
}
}, [ errorMessage, changes, resetChanges, saveChanges ]);
}, [ errorMessage, infoMessage, dismissedInfoMessage, changes, resetChanges, saveChanges, saveButtonShaking, changesButtonText ]);
return (
<div className="display">

View File

@ -30,7 +30,7 @@ const DropdownInput: FC<DropdownInputProps> = (props: DropdownInputProps) => {
useEffect(() => {
// only do this expensive version once
setDisplay(options.find(option => option.value === value)?.display ?? '');
}, []);
}, [ options, value ]);
const optionElements = useMemo(() => options.map(option => {
const className = option.value === value ? 'option selected' : 'option';
@ -40,7 +40,7 @@ const DropdownInput: FC<DropdownInputProps> = (props: DropdownInputProps) => {
setOptionsOpen(false);
};
return <div className={className} key={option.value} onClick={onClick}>{option.display}</div>;
}), [ options ]);
}), [ options, setValue, value ]);
const labelElement = useMemo(() => label && <div className="label">{label}</div>, [ label ]);

View File

@ -40,7 +40,7 @@ const TextInput: FC<TextInputProps> = React.forwardRef(function TextInput(props:
}
setValid(true);
setMessage(null);
}, [ value ]);
}, [ allowEmpty, label, maxLength, setMessage, setValid, value ]);
const labelElement = useMemo(() => label && <div className="label">{label}</div>, [ label ]);

View File

@ -18,6 +18,8 @@ const Overlay: FC<OverlayProps> = (props: OverlayProps) => {
const setOverlay = useSetRecoilState<ReactNode>(overlayState);
if (childRootRef) {
// this is alright to do since childRootRef (the ref itself) should never change for each component using this element
// eslint-disable-next-line react-hooks/rules-of-hooks
useActionWhenEscapeOrClickedOrContextOutsideEffect(childRootRef, () => setOverlay(null));
}

View File

@ -30,12 +30,12 @@ const ConnectionInfoContextMenu: FC<ConnectionInfoContextMenuProps> = (props: Co
<div className="status-circle" />
<div className="status-text">{status}</div>
</div>
)), [ setSelfStatus ]);
)), [ setSelfStatus, close ]);
const openPersonalize = useCallback(() => {
close();
setOverlay(<PersonalizeOverlay guild={guild} selfMember={selfMember} />);
}, [ close ]);
}, [ close, guild, selfMember, setOverlay ]);
const alignment = useMemo(() => ({ bottom: 'top', centerX: 'centerX' }), []);
@ -54,3 +54,4 @@ const ConnectionInfoContextMenu: FC<ConnectionInfoContextMenuProps> = (props: Co
};
export default ConnectionInfoContextMenu;

View File

@ -32,12 +32,12 @@ const GuildTitleContextMenu: FC<GuildTitleContextMenuProps> = (props: GuildTitle
return;
}
setOverlay(<GuildSettingsOverlay guild={guild} />);
}, [ close ]);
}, [ close, guild, setOverlay ]);
const openCreateChannel = useCallback(() => {
close();
setOverlay(<ChannelOverlay />);
}, [ close ]);
}, [ close, setOverlay ]);
const guildSettingsElement = useMemo(() => {
if (!isLoaded(selfMember)) return null;
@ -61,10 +61,11 @@ const GuildTitleContextMenu: FC<GuildTitleContextMenuProps> = (props: GuildTitle
);
}, [ selfMember, openCreateChannel ]);
if (guildSettingsElement === null && createChannelElement === null) return null;
const alignment = useMemo(() => ({ top: 'bottom', centerX: 'centerX' }), []);
if (guildSettingsElement === null && createChannelElement === null) return null;
return (
<ContextMenu alignment={alignment} close={close} relativeToRef={relativeToRef} realignDeps={[ selfMember ]}>
<div className="guild-title-context-menu">

View File

@ -43,14 +43,14 @@ const GuildOverviewDisplay: FC<GuildOverviewDisplayProps> = (props: GuildOvervie
if (!isLoaded(guildMeta)) return;
if (name === savedName) setName(guildMeta.value.name);
setSavedName(guildMeta.value.name);
}, [ guildMeta ]);
}, [ guildMeta, name, savedName ]);
useEffect(() => {
if (isLoaded(iconResource)) {
if (iconBuff === savedIconBuff) setIconBuff(iconResource.value.data);
setSavedIconBuff(iconResource.value.data);
}
}, [ iconResource ]);
}, [ iconBuff, iconResource, savedIconBuff ]);
const changes = useMemo(
() => name !== savedName || iconBuff?.toString('hex') !== savedIconBuff?.toString('hex'),
@ -110,7 +110,7 @@ const GuildOverviewDisplay: FC<GuildOverviewDisplayProps> = (props: GuildOvervie
}
setSaving(false);
}, [ name, iconBuff, errorMessage, saving, guild, iconBuff, savedIconBuff ]);
}, [ name, iconBuff, errorMessage, saving, savedName, savedIconBuff, guild ]);
return (
<Display

View File

@ -50,7 +50,7 @@ const ChannelElement: FC<ChannelElementProps> = (props: ChannelElementProps) =>
const launchModify = useCallback(() => {
setOverlay(<ChannelOverlay channel={channel} />);
}, [ guild, channel ]);
}, [ setOverlay, channel ]);
return (
<div className={baseClassName} onClick={setSelfActiveChannel}>

View File

@ -47,7 +47,7 @@ const MessageList: FC = () => {
result.push(<MessageElement key={guild.id + 'm#' + message.id} guild={guild} message={message} prevMessage={prevMessage} />);
}
return result;
}, [ messages ]);
}, [ guild, messages ]);
return (
<div className="message-list">

View File

@ -86,7 +86,7 @@ const AddGuildOverlay: FC<AddGuildOverlayProps> = (props: AddGuildOverlayProps)
if (exampleAvatarBuff) {
if (avatarBuff === null) setAvatarBuff(exampleAvatarBuff);
}
}, [ exampleAvatarBuff ]);
}, [ avatarBuff, exampleAvatarBuff ]);
const validationErrorMessage = useMemo(() => {
if (exampleAvatarBuffError && !avatarBuff) return 'Unable to load example avatar';

View File

@ -49,14 +49,14 @@ const ChannelOverlay: FC<ChannelOverlayProps> = (props: ChannelOverlayProps) =>
} else {
setEdited(name.length > 0 && flavorText.length > 0);
}
}, [ name, flavorText ]);
}, [ name, flavorText, channel ]);
const validationErrorMessage = useMemo(() => {
if (!edited) return null;
if (!nameInputValid && nameInputMessage) return nameInputMessage;
if (!flavorTextInputValid && flavorTextInputMessage) return flavorTextInputMessage;
return null;
}, [ nameInputValid, nameInputMessage, flavorTextInputValid, flavorTextInputMessage ]);
}, [ edited, nameInputValid, nameInputMessage, flavorTextInputValid, flavorTextInputMessage ]);
const infoMessage = useMemo(() => {
if (nameInputValid && nameInputMessage) return nameInputMessage;

View File

@ -48,11 +48,11 @@ const PersonalizeOverlay: FC<PersonalizeOverlayProps> = (props: PersonalizeOverl
if (avatarBuff === savedAvatarBuff) setAvatarBuff(avatarResource.value.data);
setSavedAvatarBuff(avatarResource.value.data);
}
}, [ avatarResource ]);
}, [ avatarBuff, avatarResource, savedAvatarBuff ]);
useEffect(() => {
displayNameInputRef.current?.focus();
}, []);
}, [ displayNameInputRef ]);
const validationErrorMessage = useMemo(() => {
if (isFailed(avatarResource)) return 'Unable to load avatar';

View File

@ -109,7 +109,7 @@ const SendMessage: FC<SendMessageProps> = (props: SendMessageProps) => {
return;
}
}
}, []);
}, [ isMounted ]);
const removeAttachment = useCallback(() => {
setAttachmentBuff(null);
@ -121,7 +121,7 @@ const SendMessage: FC<SendMessageProps> = (props: SendMessageProps) => {
const attachmentPreview = useMemo(() => {
if (!attachmentBuff || !attachmentName) return null;
return <AttachmentPreview attachmentBuff={attachmentBuff} attachmentName={attachmentName} remove={removeAttachment} />;
}, [ attachmentBuff, attachmentName ]);
}, [ attachmentBuff, attachmentName, removeAttachment ]);
// WARNING: The types on this are funky because of react's lack of explicit support for 'plaintext-only'
const contentEditableType = useMemo(() => {