我正在尝试创建一个使用某种类型的步骤栏的组件,并且该步骤栏需要一些数据(例如当前步骤,更改步骤的方法等)
我正在使用所有这些方法创建一个自定义钩子
export const useSteps = () => {
const history = useHistory();
const orderId = useSelector(getCheckinOrderId);
const checkinHasStarted = useSelector(getCheckinHasStarted);
const hasMeals = useSelector(hasMealServices);
const hasBaggage = useSelector(hasBaggageServices);
const { t } = useTranslation('Checkin');
const steps: Steps = {
findBooking: {
label: t('Find booking')
},
baggage: {
isHidden: !hasBaggage,
label: t('Baggage')
},
meal: {
isHidden: !hasMeals,
label: t('Meal')
},
seats: {
label: t('Seats')
},
payment: {
label: t('Payment')
},
boardingPass: {
label: t('Boarding pass')
}
};
const [activeStep, setActiveStep] = useState(
Object.keys(steps).findIndex(stepKey => history.location.pathname.includes(stepKey))
);
const updateActiveStep = () => {
setActiveStep(Object.keys(steps).findIndex(stepKey => history.location.pathname.includes(stepKey)));
};
console.log(activeStep); // properly updates when updateActiveStep() called
return {
steps,
activeStep,
setStep: (step: CheckinStep) => {
history.push(`/${orderId}/${step}`);
updateActiveStep();
},
nextStep: (currentStep: CheckinStep, replace = false) => {
// omitted next step logic
updateActiveStep();
},
previousStep: (currentStep: CheckinStep, replace = false) => {
//omitted prev step logic
updateActiveStep();
}
};
};
但是当我试图在组件内部获取activeStep
变量以将其传递给<Stepbar />
组件时,我看到activeStep
始终等于初始值< / p>
但是在我的自定义挂钩中,activeStep
已正确更新
我像这样使用这个钩子:
const Order: React.FC = () => {
const isCheckinStarted = useSelector(getCheckinHasStarted);
const isCheckinCompleted = useSelector(getCheckinHasCompleted);
const hasBaggage = useSelector(hasBaggageServices);
const hasMeals = useSelector(hasMealServices);
const { steps, activeStep, nextStep, setStep } = useSteps();
console.log(activeStep); // didn't udpate, always initial
return (
<div>
<Stepbar variant="blue" steps={steps} />
<Switch>
<Route
path="/:id(\d+)"
exact
render={() => {
if (isCheckinStarted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
return <Passengers />;
}}
/>
<Route
path="/:id(\d+)/baggage"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
if (!hasBaggage) {
nextStep(CheckinStep.Baggage, true);
return null;
}
return <Baggage />;
}}
/>
<Route
path="/:id(\d+)/meal"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
if (!hasMeals) {
nextStep(CheckinStep.Meal, true);
return null;
}
return <Meal />;
}}
/>
<Route
path="/:id(\d+)/seats"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
return <Seats />;
}}
/>
<Route
exact
path="/:id(\d+)/payment"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
return <Payment />;
}}
/>
<Route
path="/:id(\d+)/payment/successfull"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
return (
<PaymentResult
result="success"
onClick={reload => {
if (reload) {
location.reload();
} else {
setStep(CheckinStep.Passengers);
}
}}
/>
);
}}
/>
<Route
path="/:id(\d+)/payment/failed"
render={() => {
if (isCheckinCompleted) {
nextStep(CheckinStep.Passengers, true);
return null;
}
return <PaymentResult result="fail" onClick={() => setStep(CheckinStep.Payment)} />;
}}
/>
</Switch>
</div>
);
};
我不知道为什么。
您可以注意带有注释的行,其他代码效果很好。
答案 0 :(得分:0)
有些奇怪的事情发生了,我在初始化状态时会打印一些调试信息
const [activeStep, setActiveStep] = useState(() => {
console.log('init for first time');
return Object.keys(steps).findIndex(stepKey =>
history.location.pathname.includes(stepKey));
});
当我从父组件更改活动步骤时,每次都会看到此行(第一次初始化)
const updateActiveStep = useCallback(() => {
console.log('here');
const newStep = Math.random();
console.log('before set new step', newStep); // set random float
setActiveStep(newStep);
}, [activeStep]);
useEffect(() => {
console.log(activeStep, 'active step inside hook'); // always Int
}, [activeStep]);