diff --git a/frontend/app/components/comment/connected-comment.tsx b/frontend/app/components/comment/connected-comment.tsx index ea82b96b..80ea6d47 100644 --- a/frontend/app/components/comment/connected-comment.tsx +++ b/frontend/app/components/comment/connected-comment.tsx @@ -7,11 +7,7 @@ import './styles'; import { h, FunctionComponent } from 'preact'; -import { Comment as CommentType } from 'common/types'; - -import { useStore } from 'react-redux'; - -import { StoreState } from 'store'; +import { useAppSelector } from 'store'; import { addComment, removeComment, updateComment, setPinState, setCommentMode } from 'store/comments/actions'; import { blockUser, unblockUser, hideUser, setVerifiedStatus } from 'store/user/actions'; @@ -36,21 +32,6 @@ type ProvidedProps = Pick< | 'uploadImage' >; -const mapStateToProps = (state: StoreState, cprops: { data: CommentType }) => { - const props: ProvidedProps = { - editMode: getCommentMode(cprops.data.id)(state), - user: state.user, - isUserBanned: cprops.data.user.block || state.bannedUsers.find((u) => u.id === cprops.data.user.id) !== undefined, - post_info: state.info, - isCommentsDisabled: state.info.read_only || false, - theme: state.theme, - collapsed: getThreadIsCollapsed(cprops.data)(state), - getPreview, - uploadImage, - }; - return props; -}; - export const boundActions = bindActions({ addComment, updateComment, @@ -66,7 +47,19 @@ export const boundActions = bindActions({ export const ConnectedComment: FunctionComponent> = ( props ) => { - const providedProps = mapStateToProps(useStore().getState(), props); + const providedProps = useAppSelector((state): ProvidedProps => { + return { + editMode: getCommentMode(props.data.id)(state), + user: state.user, + isUserBanned: props.data.user.block || state.bannedUsers.find((u) => u.id === props.data.user.id) !== undefined, + post_info: state.info, + isCommentsDisabled: state.info.read_only || false, + theme: state.theme, + collapsed: getThreadIsCollapsed(props.data)(state), + getPreview, + uploadImage, + }; + }); const actions = useActions(boundActions); const intl = useIntl(); diff --git a/frontend/app/components/input/input.tsx b/frontend/app/components/input/input.tsx index 100105a0..92cb3f1a 100644 --- a/frontend/app/components/input/input.tsx +++ b/frontend/app/components/input/input.tsx @@ -4,11 +4,11 @@ import clsx from 'clsx'; import styles from './input.module.css'; type Props = JSX.HTMLAttributes & { - invalid?: boolean; + invalid?: boolean; }; export function Input({ className, type, invalid, ...props }: Props) { return ( - + ); } diff --git a/frontend/app/components/profile/profile.tsx b/frontend/app/components/profile/profile.tsx index b1930a6a..b113eee5 100644 --- a/frontend/app/components/profile/profile.tsx +++ b/frontend/app/components/profile/profile.tsx @@ -69,6 +69,10 @@ export function Profile() { function handleClickClose() { const rootElement = rootRef.current; + if (!rootElement) { + return; + } + rootElement.classList.remove(styles.rootAppear); rootElement.classList.add(styles.rootDisappear); // No need to unsubscribe because iframe will be destroyed @@ -114,7 +118,9 @@ export function Profile() { }, []); useEffect(() => { - rootRef.current.classList.add(styles.rootAppear); + if (rootRef.current) { + rootRef.current.classList.add(styles.rootAppear); + } }, []); if (!user.id) { diff --git a/frontend/app/components/root/in-view/in-view.tsx b/frontend/app/components/root/in-view/in-view.tsx index 8d9dab83..c08ef8bd 100644 --- a/frontend/app/components/root/in-view/in-view.tsx +++ b/frontend/app/components/root/in-view/in-view.tsx @@ -36,7 +36,7 @@ export function InView({ children }: Props) { const element = ref.current; const { observer, instanceMap } = getObserver(); - if (!(element.base instanceof Element)) { + if (!(element?.base instanceof Element)) { return; } diff --git a/frontend/app/components/root/root.tsx b/frontend/app/components/root/root.tsx index 2f0801eb..a214cb5d 100644 --- a/frontend/app/components/root/root.tsx +++ b/frontend/app/components/root/root.tsx @@ -323,6 +323,9 @@ export function ConnectedRoot() { const rootRef = useRef(null); useEffect(() => { + if (!rootRef.current) { + return; + } // TODO: throttle updates const observer = new MutationObserver(() => { postMessageToParent({ height: document.body.offsetHeight }); diff --git a/frontend/app/components/sort-picker.tsx b/frontend/app/components/sort-picker.tsx index 2e639154..bd099425 100644 --- a/frontend/app/components/sort-picker.tsx +++ b/frontend/app/components/sort-picker.tsx @@ -1,15 +1,14 @@ import { h } from 'preact'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { useMemo } from 'preact/hooks'; -import { useSelector, useDispatch } from 'react-redux'; -import { StoreState } from 'store'; +import { StoreState, useAppDispatch, useAppSelector } from 'store'; import { Select } from 'components/select'; import { updateSorting } from 'store/comments/actions'; import type { Sorting } from 'common/types'; export function SortPicker() { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const intl = useIntl(); const [items, itemsById] = useMemo(() => { const sortOptions = { @@ -31,7 +30,7 @@ export function SortPicker() { return [sortItems, sortById]; }, [intl]); - const sort = useSelector((s: StoreState) => s.comments.sort) || items[0].value; + const sort = useAppSelector((s: StoreState) => s.comments.sort) || items[0].value; const selected = itemsById[sort]; function handleSortChange(evt: Event) { diff --git a/frontend/app/components/textarea-autosize.tsx b/frontend/app/components/textarea-autosize.tsx index f9d57540..530914fb 100644 --- a/frontend/app/components/textarea-autosize.tsx +++ b/frontend/app/components/textarea-autosize.tsx @@ -7,22 +7,30 @@ function autoResize(textarea: HTMLTextAreaElement) { textarea.style.height = `${textarea.scrollHeight}px`; } -type Props = JSX.HTMLAttributes; +type Props = Omit, 'onInput'> & { + onInput?: (evt: JSX.TargetedEvent) => void; +}; export const TextareaAutosize = forwardRef(({ onInput, value, ...props }, externalRef) => { - const localRef = useRef(); + const localRef = useRef(null); const ref = externalRef || localRef; const handleInput: JSX.GenericEventHandler = (evt) => { + if (!ref.current) { + return; + } + if (onInput) { - return onInput.call(ref.current, evt); + return onInput(evt); } autoResize(ref.current); }; useEffect(() => { - autoResize(ref.current); + if (ref.current) { + autoResize(ref.current); + } }, [value, ref]); return