Use a key that doesn't change to avoid re-render issues; closes #2203

This commit is contained in:
Dane Everitt 2020-08-01 18:48:58 -07:00
parent 21a4ce8043
commit b92c97060b
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
6 changed files with 12 additions and 11 deletions

View file

@ -2,7 +2,7 @@ import http from '@/api/http';
import { rawDataToFileObject } from '@/api/transformers'; import { rawDataToFileObject } from '@/api/transformers';
export interface FileObject { export interface FileObject {
uuid: string; key: string;
name: string; name: string;
mode: string; mode: string;
size: number; size: number;

View file

@ -1,7 +1,6 @@
import { Allocation } from '@/api/server/getServer'; import { Allocation } from '@/api/server/getServer';
import { FractalResponseData } from '@/api/http'; import { FractalResponseData } from '@/api/http';
import { FileObject } from '@/api/server/files/loadDirectory'; import { FileObject } from '@/api/server/files/loadDirectory';
import v4 from 'uuid/v4';
export const rawDataToServerAllocation = (data: FractalResponseData): Allocation => ({ export const rawDataToServerAllocation = (data: FractalResponseData): Allocation => ({
id: data.attributes.id, id: data.attributes.id,
@ -13,7 +12,7 @@ export const rawDataToServerAllocation = (data: FractalResponseData): Allocation
}); });
export const rawDataToFileObject = (data: FractalResponseData): FileObject => ({ export const rawDataToFileObject = (data: FractalResponseData): FileObject => ({
uuid: v4(), key: `${data.attributes.is_file ? 'file' : 'dir'}_${data.attributes.name}`,
name: data.attributes.name, name: data.attributes.name,
mode: data.attributes.mode, mode: data.attributes.mode,
size: Number(data.attributes.size), size: Number(data.attributes.size),

View file

@ -1,4 +1,4 @@
import React, { useRef, useState } from 'react'; import React, { memo, useRef, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { import {
faBoxOpen, faBoxOpen,
@ -29,6 +29,7 @@ import styled from 'styled-components/macro';
import useEventListener from '@/plugins/useEventListener'; import useEventListener from '@/plugins/useEventListener';
import compressFiles from '@/api/server/files/compressFiles'; import compressFiles from '@/api/server/files/compressFiles';
import decompressFiles from '@/api/server/files/decompressFiles'; import decompressFiles from '@/api/server/files/decompressFiles';
import isEqual from 'react-fast-compare';
type ModalType = 'rename' | 'move'; type ModalType = 'rename' | 'move';
@ -50,7 +51,7 @@ const Row = ({ icon, title, ...props }: RowProps) => (
</StyledRow> </StyledRow>
); );
export default ({ file }: { file: FileObject }) => { const FileDropdownMenu = ({ file }: { file: FileObject }) => {
const onClickRef = useRef<DropdownMenu>(null); const onClickRef = useRef<DropdownMenu>(null);
const [ showSpinner, setShowSpinner ] = useState(false); const [ showSpinner, setShowSpinner ] = useState(false);
const [ modal, setModal ] = useState<ModalType | null>(null); const [ modal, setModal ] = useState<ModalType | null>(null);
@ -60,7 +61,7 @@ export default ({ file }: { file: FileObject }) => {
const { clearAndAddHttpError, clearFlashes } = useFlash(); const { clearAndAddHttpError, clearFlashes } = useFlash();
const directory = ServerContext.useStoreState(state => state.files.directory); const directory = ServerContext.useStoreState(state => state.files.directory);
useEventListener(`pterodactyl:files:ctx:${file.uuid}`, (e: CustomEvent) => { useEventListener(`pterodactyl:files:ctx:${file.key}`, (e: CustomEvent) => {
if (onClickRef.current) { if (onClickRef.current) {
onClickRef.current.triggerMenu(e.detail); onClickRef.current.triggerMenu(e.detail);
} }
@ -71,7 +72,7 @@ export default ({ file }: { file: FileObject }) => {
// For UI speed, immediately remove the file from the listing before calling the deletion function. // For UI speed, immediately remove the file from the listing before calling the deletion function.
// If the delete actually fails, we'll fetch the current directory contents again automatically. // If the delete actually fails, we'll fetch the current directory contents again automatically.
mutate(files => files.filter(f => f.uuid !== file.uuid), false); mutate(files => files.filter(f => f.key !== file.key), false);
deleteFiles(uuid, directory, [ file.name ]).catch(error => { deleteFiles(uuid, directory, [ file.name ]).catch(error => {
mutate(); mutate();
@ -166,3 +167,5 @@ export default ({ file }: { file: FileObject }) => {
</DropdownMenu> </DropdownMenu>
); );
}; };
export default memo(FileDropdownMenu, isEqual);

View file

@ -65,7 +65,7 @@ export default () => {
} }
{ {
sortFiles(files.slice(0, 250)).map(file => ( sortFiles(files.slice(0, 250)).map(file => (
<FileObjectRow key={file.uuid} file={file}/> <FileObjectRow key={file.key} file={file}/>
)) ))
} }
<MassActionsBar/> <MassActionsBar/>

View file

@ -39,7 +39,7 @@ const FileObjectRow = ({ file }: { file: FileObject }) => {
key={file.name} key={file.name}
onContextMenu={e => { onContextMenu={e => {
e.preventDefault(); e.preventDefault();
window.dispatchEvent(new CustomEvent(`pterodactyl:files:ctx:${file.uuid}`, { detail: e.clientX })); window.dispatchEvent(new CustomEvent(`pterodactyl:files:ctx:${file.key}`, { detail: e.clientX }));
}} }}
> >
<SelectFileCheckbox name={file.name}/> <SelectFileCheckbox name={file.name}/>

View file

@ -6,7 +6,6 @@ import Field from '@/components/elements/Field';
import { join } from 'path'; import { join } from 'path';
import { object, string } from 'yup'; import { object, string } from 'yup';
import createDirectory from '@/api/server/files/createDirectory'; import createDirectory from '@/api/server/files/createDirectory';
import v4 from 'uuid/v4';
import tw from 'twin.macro'; import tw from 'twin.macro';
import Button from '@/components/elements/Button'; import Button from '@/components/elements/Button';
import { mutate } from 'swr'; import { mutate } from 'swr';
@ -24,7 +23,7 @@ const schema = object().shape({
}); });
const generateDirectoryData = (name: string): FileObject => ({ const generateDirectoryData = (name: string): FileObject => ({
uuid: v4(), key: `dir_${name}`,
name: name, name: name,
mode: '0644', mode: '0644',
size: 0, size: 0,