Fix history handling not properly handling states after update to react-router v5 (#27526)
This commit is contained in:
		
							parent
							
								
									6cf9f1211b
								
							
						
					
					
						commit
						15182d1e5e
					
				@ -3,7 +3,11 @@ import React from 'react';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { Router as OriginalRouter } from 'react-router';
 | 
					import { Router as OriginalRouter } from 'react-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { LocationDescriptor, Path } from 'history';
 | 
					import type {
 | 
				
			||||||
 | 
					  LocationDescriptor,
 | 
				
			||||||
 | 
					  LocationDescriptorObject,
 | 
				
			||||||
 | 
					  Path,
 | 
				
			||||||
 | 
					} from 'history';
 | 
				
			||||||
import { createBrowserHistory } from 'history';
 | 
					import { createBrowserHistory } from 'history';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { layoutFromWindow } from 'mastodon/is_mobile';
 | 
					import { layoutFromWindow } from 'mastodon/is_mobile';
 | 
				
			||||||
@ -20,39 +24,55 @@ const browserHistory = createBrowserHistory<
 | 
				
			|||||||
const originalPush = browserHistory.push.bind(browserHistory);
 | 
					const originalPush = browserHistory.push.bind(browserHistory);
 | 
				
			||||||
const originalReplace = browserHistory.replace.bind(browserHistory);
 | 
					const originalReplace = browserHistory.replace.bind(browserHistory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function extractRealPath(path: HistoryPath) {
 | 
					function normalizePath(
 | 
				
			||||||
  if (typeof path === 'string') return path;
 | 
					  path: HistoryPath,
 | 
				
			||||||
  else return path.pathname;
 | 
					  state?: MastodonLocationState,
 | 
				
			||||||
 | 
					): LocationDescriptorObject<MastodonLocationState> {
 | 
				
			||||||
 | 
					  const location = typeof path === 'string' ? { pathname: path } : { ...path };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (location.state === undefined && state !== undefined) {
 | 
				
			||||||
 | 
					    location.state = state;
 | 
				
			||||||
 | 
					  } else if (
 | 
				
			||||||
 | 
					    location.state !== undefined &&
 | 
				
			||||||
 | 
					    state !== undefined &&
 | 
				
			||||||
 | 
					    process.env.NODE_ENV === 'development'
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    // eslint-disable-next-line no-console
 | 
				
			||||||
 | 
					    console.log(
 | 
				
			||||||
 | 
					      'You should avoid providing a 2nd state argument to push when the 1st argument is a location-like object that already has state; it is ignored',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (
 | 
				
			||||||
 | 
					    layoutFromWindow() === 'multi-column' &&
 | 
				
			||||||
 | 
					    !location.pathname?.startsWith('/deck')
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    location.pathname = `/deck${location.pathname}`;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return location;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
browserHistory.push = (path: HistoryPath, state?: MastodonLocationState) => {
 | 
					browserHistory.push = (path: HistoryPath, state?: MastodonLocationState) => {
 | 
				
			||||||
  state = state ?? {};
 | 
					  const location = normalizePath(path, state);
 | 
				
			||||||
  state.fromMastodon = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const realPath = extractRealPath(path);
 | 
					  location.state = location.state ?? {};
 | 
				
			||||||
  if (!realPath) return;
 | 
					  location.state.fromMastodon = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
 | 
					  originalPush(location);
 | 
				
			||||||
    originalPush(`/deck${realPath}`, state);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    originalPush(path, state);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
 | 
					browserHistory.replace = (path: HistoryPath, state?: MastodonLocationState) => {
 | 
				
			||||||
 | 
					  const location = normalizePath(path, state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!location.pathname) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (browserHistory.location.state?.fromMastodon) {
 | 
					  if (browserHistory.location.state?.fromMastodon) {
 | 
				
			||||||
    state = state ?? {};
 | 
					    location.state = location.state ?? {};
 | 
				
			||||||
    state.fromMastodon = true;
 | 
					    location.state.fromMastodon = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const realPath = extractRealPath(path);
 | 
					  originalReplace(location);
 | 
				
			||||||
  if (!realPath) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (layoutFromWindow() === 'multi-column' && !realPath.startsWith('/deck')) {
 | 
					 | 
				
			||||||
    originalReplace(`/deck${realPath}`, state);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    originalReplace(path, state);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
 | 
					export const Router: React.FC<PropsWithChildren> = ({ children }) => {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user