Refactor to function component

This commit is contained in:
Nathan Bierema 2023-08-07 10:30:21 -04:00
parent c3e7e8cf56
commit 5cb48ed15a

View File

@ -1,6 +1,4 @@
import React, { PureComponent, RefCallback } from 'react'; import React, { useCallback, useLayoutEffect, useRef } from 'react';
import { Drake } from 'dragula';
import dragula from 'react-dragula';
import { Action } from 'redux'; import { Action } from 'redux';
import { PerformAction } from '@redux-devtools/core'; import { PerformAction } from '@redux-devtools/core';
import { StylingFunction } from 'react-base16-styling'; import { StylingFunction } from 'react-base16-styling';
@ -44,71 +42,11 @@ interface Props<A extends Action<unknown>> {
lastActionId: number; lastActionId: number;
} }
export default class ActionList< function scrollToBottom(node: HTMLDivElement) {
A extends Action<unknown>, node.scrollTop = node.scrollHeight;
> extends PureComponent<Props<A>> {
node?: HTMLDivElement | null;
scrollDown?: boolean;
drake?: Drake;
UNSAFE_componentWillReceiveProps(nextProps: Props<A>) {
const node = this.node;
if (!node) {
this.scrollDown = true;
} else if (this.props.lastActionId !== nextProps.lastActionId) {
const { scrollTop, offsetHeight, scrollHeight } = node;
this.scrollDown =
Math.abs(scrollHeight - (scrollTop + offsetHeight)) < 50;
} else {
this.scrollDown = false;
}
} }
componentDidMount() { export default function ActionListFunction<A extends Action<unknown>>({
this.scrollDown = true;
this.scrollToBottom();
if (!this.props.draggableActions) return;
const container = this.node!;
this.drake = dragula([container], {
copy: false,
copySortSource: false,
mirrorContainer: container,
accepts: (el, target, source, sibling) =>
!sibling || !!parseInt(sibling.getAttribute('data-id')!),
moves: (el, source, handle) =>
!!parseInt(el!.getAttribute('data-id')!) &&
handle!.className.indexOf('selectorButton') !== 0,
}).on('drop', (el, target, source, sibling) => {
let beforeActionId = this.props.actionIds.length;
if (sibling && sibling.className.indexOf('gu-mirror') === -1) {
beforeActionId = parseInt(sibling.getAttribute('data-id')!);
}
const actionId = parseInt(el.getAttribute('data-id')!);
this.props.onReorderAction(actionId, beforeActionId);
});
}
componentWillUnmount() {
if (this.drake) this.drake.destroy();
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom() {
if (this.scrollDown && this.node) {
this.node.scrollTop = this.node.scrollHeight;
}
}
getRef: RefCallback<HTMLDivElement> = (node) => {
this.node = node;
};
render() {
const {
styling, styling,
actions, actions,
actionIds, actionIds,
@ -126,7 +64,30 @@ export default class ActionList<
onCommit, onCommit,
onSweep, onSweep,
onJumpToState, onJumpToState,
} = this.props; lastActionId,
}: Props<A>) {
const nodeRef = useRef<HTMLDivElement | null>(null);
const prevLastActionId = useRef<number | undefined>();
useLayoutEffect(() => {
if (nodeRef.current && prevLastActionId.current !== lastActionId) {
const { scrollTop, offsetHeight, scrollHeight } = nodeRef.current;
if (Math.abs(scrollHeight - (scrollTop + offsetHeight)) < 50) {
scrollToBottom(nodeRef.current);
}
}
prevLastActionId.current = lastActionId;
}, [lastActionId]);
const setNodeRef = useCallback((node: HTMLDivElement | null) => {
if (node && !nodeRef.current) {
scrollToBottom(node);
}
nodeRef.current = node;
}, []);
const lowerSearchValue = searchValue && searchValue.toLowerCase(); const lowerSearchValue = searchValue && searchValue.toLowerCase();
const filteredActionIds = searchValue const filteredActionIds = searchValue
? actionIds.filter( ? actionIds.filter(
@ -159,7 +120,7 @@ export default class ActionList<
<div <div
data-testid="actionListRows" data-testid="actionListRows"
{...styling('actionListRows')} {...styling('actionListRows')}
ref={this.getRef} ref={setNodeRef}
> >
{filteredActionIds.map((actionId) => ( {filteredActionIds.map((actionId) => (
<ActionListRow <ActionListRow
@ -192,4 +153,3 @@ export default class ActionList<
</div> </div>
); );
} }
}