From 2eba4eaf59e80b32ca38ab5cfbb2c79e98f3fe7c Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Wed, 5 Jul 2023 16:59:28 +0800 Subject: [PATCH] Prevent re-render timeline in multi-column mode --- src/components/columns.jsx | 6 +++++- src/pages/hashtag.jsx | 19 +++++++++++-------- src/pages/list.jsx | 5 +++-- src/pages/mentions.jsx | 5 +++-- src/pages/public.jsx | 11 +++++++---- src/pages/trending.jsx | 9 +++++---- src/utils/useTitle.js | 6 +++--- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/components/columns.jsx b/src/components/columns.jsx index d79ab5a4..0f1f0237 100644 --- a/src/components/columns.jsx +++ b/src/components/columns.jsx @@ -18,6 +18,8 @@ function Columns() { const snapStates = useSnapshot(states); const { shortcuts } = snapStates; + console.debug('RENDER Columns', shortcuts); + const components = shortcuts.map((shortcut) => { if (!shortcut) return null; const { type, ...params } = shortcut; @@ -33,7 +35,9 @@ function Columns() { trending: Trending, }[type]; if (!Component) return null; - return ; + return ( + + ); }); useHotkeys(['1', '2', '3', '4', '5', '6', '7', '8', '9'], (e, handler) => { diff --git a/src/pages/hashtag.jsx b/src/pages/hashtag.jsx index 76337280..b81a6744 100644 --- a/src/pages/hashtag.jsx +++ b/src/pages/hashtag.jsx @@ -25,9 +25,9 @@ const LIMIT = 20; const TAGS_LIMIT_PER_MODE = 4; const TOTAL_TAGS_LIMIT = TAGS_LIMIT_PER_MODE + 1; -function Hashtags(props) { - const navigate = useNavigate(); - let { hashtag, ...params } = useParams(); +function Hashtags({ columnMode, ...props }) { + // const navigate = useNavigate(); + let { hashtag, ...params } = columnMode ? {} : useParams(); if (props.hashtag) hashtag = props.hashtag; let hashtags = hashtag.trim().split(/[\s+]+/); hashtags.sort(); @@ -217,11 +217,14 @@ function Hashtags(props) { ) { hashtags.push(newHashtag); hashtags.sort(); - navigate( - instance - ? `/${instance}/t/${hashtags.join('+')}` - : `/t/${hashtags.join('+')}`, - ); + // navigate( + // instance + // ? `/${instance}/t/${hashtags.join('+')}` + // : `/t/${hashtags.join('+')}`, + // ); + location.hash = instance + ? `/${instance}/t/${hashtags.join('+')}` + : `/t/${hashtags.join('+')}`; } }} > diff --git a/src/pages/list.jsx b/src/pages/list.jsx index d42d5109..3c360288 100644 --- a/src/pages/list.jsx +++ b/src/pages/list.jsx @@ -24,7 +24,7 @@ function List(props) { const snapStates = useSnapshot(states); const { masto, instance } = api(); const id = props?.id || useParams()?.id; - const navigate = useNavigate(); + // const navigate = useNavigate(); const latestItem = useRef(); // const [reloadCount, reload] = useReducer((c) => c + 1, 0); @@ -154,7 +154,8 @@ function List(props) { setList(result.list); // reload(); } else if (result.state === 'deleted') { - navigate('/l'); + // navigate('/l'); + location.hash = '/l'; } setShowListAddEditModal(false); }} diff --git a/src/pages/mentions.jsx b/src/pages/mentions.jsx index 3e77f0f6..a57d9e2e 100644 --- a/src/pages/mentions.jsx +++ b/src/pages/mentions.jsx @@ -8,11 +8,12 @@ import { saveStatus } from '../utils/states'; import useTitle from '../utils/useTitle'; const LIMIT = 20; +const emptySearchParams = new URLSearchParams(); -function Mentions(props) { +function Mentions({ columnMode, ...props }) { useTitle('Mentions', '/mentions'); const { masto, instance } = api(); - const [searchParams] = useSearchParams(); + const [searchParams] = columnMode ? [emptySearchParams] : useSearchParams(); const type = props?.type || searchParams.get('type'); const mentionsIterator = useRef(); diff --git a/src/pages/public.jsx b/src/pages/public.jsx index 8f4a1145..b634f236 100644 --- a/src/pages/public.jsx +++ b/src/pages/public.jsx @@ -14,16 +14,16 @@ import useTitle from '../utils/useTitle'; const LIMIT = 20; -function Public({ local, ...props }) { +function Public({ local, columnMode, ...props }) { const snapStates = useSnapshot(states); const isLocal = !!local; - const params = useParams(); + const params = columnMode ? {} : useParams(); const { masto, instance } = api({ instance: props?.instance || params.instance, }); const title = `${isLocal ? 'Local' : 'Federated'} timeline (${instance})`; useTitle(title, isLocal ? `/:instance?/p/l` : `/:instance?/p`); - const navigate = useNavigate(); + // const navigate = useNavigate(); const latestItem = useRef(); const publicIterator = useRef(); @@ -128,7 +128,10 @@ function Public({ local, ...props }) { } if (newInstance) { newInstance = newInstance.toLowerCase().trim(); - navigate(isLocal ? `/${newInstance}/p/l` : `/${newInstance}/p`); + // navigate(isLocal ? `/${newInstance}/p/l` : `/${newInstance}/p`); + location.hash = isLocal + ? `/${newInstance}/p/l` + : `/${newInstance}/p`; } }} > diff --git a/src/pages/trending.jsx b/src/pages/trending.jsx index 92c03b21..743fcaad 100644 --- a/src/pages/trending.jsx +++ b/src/pages/trending.jsx @@ -15,15 +15,15 @@ import useTitle from '../utils/useTitle'; const LIMIT = 20; -function Trending(props) { +function Trending({ columnMode, ...props }) { const snapStates = useSnapshot(states); - const params = useParams(); + const params = columnMode ? {} : useParams(); const { masto, instance } = api({ instance: props?.instance || params.instance, }); const title = `Trending (${instance})`; useTitle(title, `/:instance?/trending`); - const navigate = useNavigate(); + // const navigate = useNavigate(); const latestItem = useRef(); const [hashtags, setHashtags] = useState([]); @@ -151,7 +151,8 @@ function Trending(props) { } if (newInstance) { newInstance = newInstance.toLowerCase().trim(); - navigate(`/${newInstance}/trending`); + // navigate(`/${newInstance}/trending`); + location.hash = `/${newInstance}/trending`; } }} > diff --git a/src/utils/useTitle.js b/src/utils/useTitle.js index 17f32fb4..af9b8b44 100644 --- a/src/utils/useTitle.js +++ b/src/utils/useTitle.js @@ -1,4 +1,4 @@ -import { useEffect } from 'preact/hooks'; +import { useLayoutEffect } from 'preact/hooks'; import { matchPath } from 'react-router-dom'; import { subscribeKey } from 'valtio/utils'; @@ -23,13 +23,13 @@ export default function useTitle(title, path) { } else if (path) { matched = matchPath(path, currentLocation); } - console.log('setTitle', { title, path, currentLocation, paths, matched }); + console.debug('setTitle', { title, path, currentLocation, paths, matched }); if (matched) { document.title = title ? `${title} / ${CLIENT_NAME}` : CLIENT_NAME; } } - useEffect(() => { + useLayoutEffect(() => { setTitle(); return subscribeKey(states, 'currentLocation', setTitle); }, [title, path]);