我们决定在我们的应用程序上实现一个简单的入门教程,在本地一切都很顺利,但一旦我们将其部署到生产环境中,它就会崩溃,并在devtools上显示下一个错误:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '0')
很难对此进行调试并找出问题所在,因为它是在生产环境中引起的,就像是闭着眼睛进行调试一样。
控制台显示的错误/错误是未定义的,逻辑也会在本地崩溃,但事实并非如此
该错误是在我们通过第一步后导致的,如您在此视频中所见(您还可以看到它是如何在本地工作的:VIDEO WITH THE ISSUE
他们的方式,其实施的joyride包括两个大键,第一个它的joyride wrapper
:
import { useEffect, useState } from 'react';
import Joyride, { CallBackProps, STATUS, Step } from 'react-joyride';
import { Tooltip } from './components/tool-tip';
import { OnboardingTourJoyrideProps, ValidSteps } from '../../types/onboarding-tour';
import { useGuidedTour } from '../../hooks/use-guided-tour';
export function OnboardingTourJoyride({ start, stepToCheck }: OnboardingTourJoyrideProps): JSX.Element {
const { dashBoardSteps, terminalAppSteps, cloudAppSteps } = useGuidedTour();
const [steps, setSteps] = useState<Step[]>(dashBoardSteps);
const [run, setRun] = useState<boolean>(false);
const [resetTour, setResetTour] = useState<boolean>(false);
const [stepToInitRestart, setStepToInitRestart] = useState<number>(0);
function handleSteps() {
switch (stepToCheck) {
case ValidSteps.DASHBOARD_STEPS:
setSteps(dashBoardSteps);
setStepToInitRestart(dashBoardSteps.length - 1);
break;
case ValidSteps.TERMINAL_APP_STEPS:
setSteps(terminalAppSteps);
setStepToInitRestart(terminalAppSteps.length - 1);
break;
case ValidSteps.CLOUD_APP_STEPS:
setSteps(cloudAppSteps);
setStepToInitRestart(cloudAppSteps.length - 1);
}
}
useEffect(() => {
const onboardinIsCompletedOrSkipped = handleCheckIfTourIsComplete();
if (!onboardinIsCompletedOrSkipped) {
handleSteps();
if (start) setRun(true);
}
}, [start]);
useEffect(() => {
if (resetTour) {
setRun(true);
setResetTour(false);
}
}, [resetTour]);
function handlePropertyToSaveOnLocalStorage() {
switch (stepToCheck) {
case ValidSteps.DASHBOARD_STEPS:
localStorage.setItem('ONBOARDING_TOUR_DASHBOARD', 'true');
break;
case ValidSteps.TERMINAL_APP_STEPS:
localStorage.setItem('ONBOARDING_TOUR_TERMINAL_APP', 'true');
break;
case ValidSteps.CLOUD_APP_STEPS:
localStorage.setItem('ONBOARDING_TOUR_CLOUD_APP', 'true');
break;
}
}
function handleCheckIfTourIsComplete() {
if (stepToCheck === ValidSteps.DASHBOARD_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_DASHBOARD');
} else if (stepToCheck === ValidSteps.TERMINAL_APP_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_TERMINAL_APP');
} else if (stepToCheck === ValidSteps.CLOUD_APP_STEPS) {
return localStorage.getItem('ONBOARDING_TOUR_CLOUD_APP');
}
}
function handleJoyrideCallback(data: CallBackProps) {
const { status, action, index } = data;
console.log(data);
const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED];
if (index === stepToInitRestart && status === STATUS.SKIPPED) {
setRun(false);
setResetTour(true);
}
if (finishedStatuses.includes(status)) {
if (action === 'skip') {
setRun(false);
handlePropertyToSaveOnLocalStorage();
}
setRun(false);
handlePropertyToSaveOnLocalStorage();
}
}
return (
<Joyride
tooltipComponent={Tooltip}
disableScrolling={true}
callback={handleJoyrideCallback}
continuous
hideCloseButton
run={run}
scrollToFirstStep
showProgress={false}
showSkipButton={true}
steps={steps}
styles={{
options: {
zIndex: 10000,
},
}}
/>
);
}
它是一个简单的 Package 器,包含在应用程序中重用相同组件的所有逻辑
另一个是自定义工具提示组件:
import { Box, CloseButton, Flex, Text } from '@chakra-ui/react';
import { TooltipRenderProps } from 'react-joyride';
import { Button } from '../../button';
import { useIntl } from 'react-intl';
export function Tooltip({
backProps,
continuous,
index,
isLastStep,
primaryProps,
skipProps,
step,
tooltipProps,
size,
}: TooltipRenderProps): JSX.Element {
const intl = useIntl();
const steps = {
currentStep: index,
stepsLength: size - 2,
};
function handleResetOrBackStep(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
if (isLastStep) {
skipProps.onClick(e);
} else {
backProps.onClick(e);
}
}
function handleCloseButton(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
if (isLastStep) {
primaryProps.onClick(e);
} else {
skipProps.onClick(e);
}
}
function handleFowardButton() {
return continuous
? index !== 0 && !isLastStep
? intl.formatMessage({ id: 'buttons.next' })
: isLastStep
? intl.formatMessage({ id: 'buttons.finish' })
: intl.formatMessage({ id: 'buttons.startTour' })
: null;
}
function handleShowStepsCounter() {
return index !== 0 && !isLastStep ? (
<Text fontSize="16px">
{intl.formatMessage(
{ id: 'onboardingTour.toolTip.stepsCounter' },
{
currentStep: steps.currentStep,
totalSteps: steps.stepsLength,
},
)}
</Text>
) : (
!isLastStep && (
<Button variant="outline" {...skipProps}>
{intl.formatMessage({ id: 'buttons.skipTour' })}
</Button>
)
);
}
function handleBackwardButton() {
return isLastStep
? intl.formatMessage({ id: 'buttons.restartTour' })
: intl.formatMessage({ id: 'buttons.previous' });
}
return (
<Box {...tooltipProps} background="white" p="48px" w="100%" borderRadius="6px">
<Box padding="md">
<Flex justifyContent="space-between" align="baseline" marginBottom="15px">
{step.title && (
<Text fontSize="20px" fontWeight="700">
{step.title}
</Text>
)}
<CloseButton onClick={e => handleCloseButton(e)} />
</Flex>
{step.content && (
<Box>
<Text w="504px" fontSize="16px" fontWeight="400" lineHeight="26px" marginBottom="48px">
{step.content}
</Text>
</Box>
)}
</Box>
<Box>
<Flex justifyContent="space-between" align="center">
{handleShowStepsCounter()}
<Flex w={isLastStep ? '100%' : ''} justifyContent="space-between">
{index !== 0 && (
<Button marginRight="12px" variant="outline" onClick={e => handleResetOrBackStep(e)}>
{handleBackwardButton()}
</Button>
)}
<Button h="35px" {...primaryProps}>
{handleFowardButton()}
</Button>
</Flex>
</Flex>
</Box>
</Box>
);
}
我不知道是否有人有过类似的经历,我在谷歌上搜索了所有的SO和库存储库中的问题。还有一点很奇怪,因为在我使用react-joyride并部署到生产环境中时,没有任何问题。为了让大家了解上下文,我们使用了一个名为Gasket
的框架next。
1条答案
按热度按时间z4iuyo4d1#
有同样的问题。这里是解决方案-https://github.com/gilbarbara/react-joyride/issues/857(也更新nextjs到13. 1. 1修复了这个问题)