Improve initial loading with useOnMount

This commit is contained in:
Corey 2024-05-21 11:30:06 -04:00
parent 11cb35d0ac
commit 20f5b9fa13
Signed by: coco
GPG Key ID: 051138DA6AEE3E60
4 changed files with 61 additions and 80 deletions

View File

@ -9,6 +9,7 @@ import {
Typography,
} from '@mui/material';
import IconButton from '@mui/material/IconButton';
import { useOnMount } from '@mui/x-data-grid';
import { useCallback, useEffect, useState } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { fetchDataFromBackend } from '../../apiUtil';
@ -38,7 +39,6 @@ export default function Header({
const { progress, setProgress, showAlert } = useLoadingContext();
const [showSearchServer, setShowSearchServer] = useState(false);
const [filtersApplied, setFiltersApplied] = useState(false);
const [initialFetch, setInitialFetch] = useState(true);
const toggleShowSearchServer = () => {
setShowSearchServer((prev) => !prev);
};
@ -68,16 +68,15 @@ export default function Header({
}, 500);
}, [showAlert, setServers, setProgress]);
useOnMount(() => {
fetchServerData();
});
useEffect(() => {
// TODO: Check if there's a better way to do this than "initialFetch" state, see also SearchServers
if (initialFetch) {
fetchServerData();
setInitialFetch(false);
}
setFiltersApplied(
JSON.stringify(searchState) !== JSON.stringify(SearchStateDefaults)
);
}, [initialFetch, fetchServerData, searchState]);
}, [searchState]);
return (
<Box>

View File

@ -12,6 +12,7 @@ import {
Tooltip,
Typography,
} from '@mui/material';
import { useOnMount } from '@mui/x-data-grid';
import { useEffect, useRef, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { SearchState, SearchStateDefaults } from '../../data/SearchState';
@ -57,33 +58,25 @@ export default function SearchServers({
const location = useLocation();
const [initialPath] = useState(location.pathname);
const [contentHeight, setContentHeight] = useState(0);
const [initialLoad, setInitialLoad] = useState(true);
useOnMount(() => {
if (initialPath === '/') {
const params = parseSearchParams(location.search);
if (JSON.stringify(params) !== JSON.stringify(SearchStateDefaults)) {
setSearchState(params);
}
}
});
useEffect(() => {
// Populate search state with URL params only if loading the home page
// Home page manages updating URL params
// TODO: Check if there's a better way to do this than "initialLoad" state, see also Header
if (initialLoad) {
if (initialPath === '/') {
const params = parseSearchParams(location.search);
if (JSON.stringify(params) !== JSON.stringify(SearchStateDefaults)) {
setSearchState(params);
}
}
setInitialLoad(false);
}
if (showSearchServer && containerRef.current) {
setContentHeight(containerRef.current.scrollHeight);
} else {
setContentHeight(0);
}
}, [
showSearchServer,
location.search,
setSearchState,
initialPath,
initialLoad,
]);
}, [showSearchServer]);
const handleChange = (
name: string,

View File

@ -54,17 +54,17 @@ MAIN.ENABLE_TVR`;
variant="body1"
color={(theme) => alpha(theme.palette.text.primary, 0.87)}
>
Ixion is a catalog of Final Fantasy XI private servers running the{' '}
Ixion is a directory of public{' '}
<Link
href="https://github.com/LandSandBoat/server"
target="_blank"
>
LandSandBoat
</Link>{' '}
software (or serving their API). Servers are updated every 10
minutes and are removed after a variable amount of
disconnectivity. All information is gathered directly from the
listed servers.
(LSB) servers. Servers are updated every 10 minutes and are
unlisted after a variable amount of disconnectivity proportional
to their time listed (maximum 24 hours). All information is
gathered directly from the listed servers.
</Typography>
</Box>
<Box className="mb-3">
@ -158,7 +158,7 @@ MAIN.ENABLE_TVR`;
<CodeCard title="api.lua" content={apiLua} />
The world server needs to be restarted after any changes to any
of the settings. If you set <b>DO_NOT_TRACK</b> to <b>true</b>,
your server will be removed on the next update.
your server will be unlisted on the next update.
</Typography>
</Box>
<Box className="mb-3">
@ -170,30 +170,12 @@ MAIN.ENABLE_TVR`;
variant="body1"
color={(theme) => alpha(theme.palette.text.primary, 0.87)}
>
Anything that differs from the default LSB settings will be
displayed in the &quot;Settings Summary&quot; section for a
server. The following settings are always included as part of
the UI:
Any LSB settings that differ from the defaults will be displayed
in the &quot;Settings Summary&quot; section. The following
settings are always included as part of the UI:
<CodeCard title="Settings" content={recommendedSettings} />
</Typography>
</Box>
<Box className="mb-3">
<Typography align="center" variant="h6">
What if my server isn&apos;t running LSB?
</Typography>
<Typography
component="p"
variant="body1"
color={(theme) => alpha(theme.palette.text.primary, 0.87)}
>
If you&apos;re not running LSB, you could fake the API response.
You&apos;ll want to look at the LSB settings and serve whatever
relevant changes you&apos;ve made using the LSB equivalent, the
above listed settings at minimum. Settings should be served at{' '}
<b>/api/settings</b> and total active sessions should be served
at <b>/api/sessions</b>.
</Typography>
</Box>
</AccordionDetails>
</Accordion>
</Card>

View File

@ -1,5 +1,6 @@
import { Box } from '@mui/material';
import { useEffect, useState } from 'react';
import { useOnMount } from '@mui/x-data-grid';
import { useCallback, useState } from 'react';
import { useParams } from 'react-router-dom';
import { fetchDataFromBackend, fetchDemo } from '../apiUtil';
import ErrorCard from '../components/ErrorCard';
@ -9,41 +10,47 @@ import { useLoadingContext } from '../context/LoadingContext';
import { ServerData } from '../data/ServerData';
export default function ServerDetails() {
const { showAlert } = useLoadingContext();
const { url } = useParams();
const [server, setServer] = useState<ServerData>();
const [error, setError] = useState<string>('');
const [server, setServer] = useState<ServerData | null>();
const { setProgress, showAlert } = useLoadingContext();
useEffect(() => {
let data: ServerData;
const fetchServerData = async () => {
try {
if (url === 'demo') {
data = await fetchDemo();
} else {
data = await fetchDataFromBackend(`server/?url=${url}`);
}
} catch (err) {
if (err instanceof Error) {
showAlert({
message: err.message,
severity: 'error',
});
} else {
setError('An unknown error occurred.');
}
const fetchServerData = useCallback(async () => {
let data: ServerData | null = null;
try {
setProgress(25);
if (url === 'demo') {
data = await fetchDemo();
} else {
data = await fetchDataFromBackend(`server/?url=${url}`);
}
} catch (err) {
if (err instanceof Error) {
showAlert({
message: err.message,
severity: 'error',
});
} else {
showAlert({
message: 'An unknown error occurred.',
severity: 'error',
});
}
}
setServer(data);
setProgress(100);
setTimeout(() => {
setProgress(0);
}, 500);
}, [url, showAlert, setServer, setProgress]);
setServer(data);
};
useOnMount(() => {
fetchServerData();
}, [url, setServer, showAlert, setError]);
});
return (
<Box>
{error || !server ? (
<ErrorCard error={error} />
{!server ? (
<ErrorCard error="" />
) : (
<ServerCard server={server}>
{server.settings && (