mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 04:50:36 +03:00
M:BlockNavigation should not cause rerenders
This commit is contained in:
parent
4eb670714d
commit
6f1afc68ad
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { createContext, use, useEffect, useState } from 'react';
|
import { createContext, use, useEffect, useRef, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
|
||||||
export interface NavigationProps {
|
export interface NavigationProps {
|
||||||
|
@ -19,8 +19,7 @@ interface INavigationContext {
|
||||||
|
|
||||||
canBack: () => boolean;
|
canBack: () => boolean;
|
||||||
|
|
||||||
isBlocked: boolean;
|
setRequireConfirmation: (value: boolean) => void;
|
||||||
setIsBlocked: (value: boolean) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NavigationContext = createContext<INavigationContext | null>(null);
|
export const NavigationContext = createContext<INavigationContext | null>(null);
|
||||||
|
@ -35,11 +34,11 @@ export const useConceptNavigation = () => {
|
||||||
export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
const router = useNavigate();
|
const router = useNavigate();
|
||||||
|
|
||||||
const [isBlocked, setIsBlocked] = useState(false);
|
const isBlocked = useRef(false);
|
||||||
const [internalNavigation, setInternalNavigation] = useState(false);
|
const [internalNavigation, setInternalNavigation] = useState(false);
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
return !isBlocked || confirm('Изменения не сохранены. Вы уверены что хотите совершить переход?');
|
return !isBlocked.current || confirm('Изменения не сохранены. Вы уверены что хотите совершить переход?');
|
||||||
}
|
}
|
||||||
|
|
||||||
function canBack() {
|
function canBack() {
|
||||||
|
@ -50,7 +49,7 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
if (props.newTab) {
|
if (props.newTab) {
|
||||||
window.open(`${props.path}`, '_blank');
|
window.open(`${props.path}`, '_blank');
|
||||||
} else if (props.force || validate()) {
|
} else if (props.force || validate()) {
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
setInternalNavigation(true);
|
setInternalNavigation(true);
|
||||||
Promise.resolve(router(props.path, { viewTransition: true })).catch(console.error);
|
Promise.resolve(router(props.path, { viewTransition: true })).catch(console.error);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +59,7 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
if (props.newTab) {
|
if (props.newTab) {
|
||||||
window.open(`${props.path}`, '_blank');
|
window.open(`${props.path}`, '_blank');
|
||||||
} else if (props.force || validate()) {
|
} else if (props.force || validate()) {
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
setInternalNavigation(true);
|
setInternalNavigation(true);
|
||||||
return router(props.path, { viewTransition: true });
|
return router(props.path, { viewTransition: true });
|
||||||
}
|
}
|
||||||
|
@ -68,14 +67,14 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
|
|
||||||
function replace(props: Omit<NavigationProps, 'newTab'>) {
|
function replace(props: Omit<NavigationProps, 'newTab'>) {
|
||||||
if (props.force || validate()) {
|
if (props.force || validate()) {
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
Promise.resolve(router(props.path, { replace: true, viewTransition: true })).catch(console.error);
|
Promise.resolve(router(props.path, { replace: true, viewTransition: true })).catch(console.error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAsync(props: Omit<NavigationProps, 'newTab'>): void | Promise<void> {
|
function replaceAsync(props: Omit<NavigationProps, 'newTab'>): void | Promise<void> {
|
||||||
if (props.force || validate()) {
|
if (props.force || validate()) {
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
return router(props.path, { replace: true, viewTransition: true });
|
return router(props.path, { replace: true, viewTransition: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,14 +82,14 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
function back(force?: boolean) {
|
function back(force?: boolean) {
|
||||||
if (force || validate()) {
|
if (force || validate()) {
|
||||||
Promise.resolve(router(-1)).catch(console.error);
|
Promise.resolve(router(-1)).catch(console.error);
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function forward(force?: boolean) {
|
function forward(force?: boolean) {
|
||||||
if (force || validate()) {
|
if (force || validate()) {
|
||||||
Promise.resolve(router(1)).catch(console.error);
|
Promise.resolve(router(1)).catch(console.error);
|
||||||
setIsBlocked(false);
|
isBlocked.current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +103,7 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
back,
|
back,
|
||||||
forward,
|
forward,
|
||||||
canBack,
|
canBack,
|
||||||
isBlocked,
|
setRequireConfirmation: (value: boolean) => (isBlocked.current = value)
|
||||||
setIsBlocked
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -114,9 +112,9 @@ export const NavigationState = ({ children }: React.PropsWithChildren) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useBlockNavigation(isBlocked: boolean) {
|
export function useBlockNavigation(isBlocked: boolean) {
|
||||||
const router = useConceptNavigation();
|
const { setRequireConfirmation } = useConceptNavigation();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
router.setIsBlocked(isBlocked);
|
setRequireConfirmation(isBlocked);
|
||||||
return () => router.setIsBlocked(false);
|
return () => setRequireConfirmation(false);
|
||||||
}, [router, isBlocked]);
|
}, [setRequireConfirmation, isBlocked]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user