I'm using NextJS 15 and Jotai. I'm tring to get withImmer to work on different pages (app directory) within a flow. What I mean is that I within a main directory called signup I have folders in it named step2, step3, etc.. I have one layout in the signup directory which has a progress bar that all sub-folders inherit from. My problem is that because the progress bar only renders once and not on each page the status of my progress bar doesn't get updated. I've tried using a store provider and that didn't work. I was hoping the immer would work but it doesn't either. Does anyone have any ideas on how to make this work? Below is some of the code I have.
export const stepsAtom = atom<Step[]>([
{ id: 1, name: 'Diabetes Type', href: '#', status: 'current' },
{ id: 2, name: 'Gender', href: '#', status: 'upcoming' },
{ id: 3, name: 'Age', href: '#', status: 'upcoming' },
{ id: 4, name: 'Height', href: '#', status: 'upcoming' },
{ id: 5, name: 'Weight', href: '#', status: 'upcoming' },
{ id: 6, name: 'Medical Conditions', href: '#', status: 'upcoming' },
{ id: 7, name: 'Physically Active', href: '#', status: 'upcoming' },
{ id: 8, name: 'Exercise', href: '#', status: 'upcoming' }
]);
export const derivedStepsAtomImmer = withImmer(stepsAtom);
Progress bar:
export default function ProgressBar() {
// const steps = initialSteps;
const [toImmerSteps] = useImmerAtom(derivedStepsAtomImmer);
return (
<nav aria-label="Progress">
<ol role="list" className="divide-y divide-gray-300 rounded-md border border-gray-300 md:flex md:divide-y-0">
{toImmerSteps.map((step, stepIdx) => (
<li key={step.name} className="relative md:flex md:flex-1">
{step.status === 'complete' ? (
<a href={step.href} className="group flex w-full items-center">
<span className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full bg-indigo-600 group-hover:bg-indigo-800">
<CheckIcon aria-hidden="true" className="size-6 text-white" />
</span>
<span className="ml-4 text-sm font-medium text-gray-900">{step.name}</span>
</span>
</a>
) : step.status === 'current' ? (
<a href={step.href} aria-current="step" className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-indigo-600">
<span className="text-indigo-600">{step.id}</span>
</span>
<span className="ml-4 text-sm font-medium text-indigo-600">{step.name}</span>
</a>
) : (
<a href={step.href} className="group flex items-center">
<span className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-gray-300 group-hover:border-gray-400">
<span className="text-gray-500 group-hover:text-gray-900">{step.id}</span>
</span>
<span className="ml-4 text-sm font-medium text-gray-500 group-hover:text-gray-900">{step.name}</span>
</span>
</a>
)}
{stepIdx !== step.length - 1 ? (
<>
{/* Arrow separator for lg screens and up */}
<div aria-hidden="true" className="absolute right-0 top-0 hidden h-full w-5 md:block">
<svg fill="none" viewBox="0 0 22 80" preserveAspectRatio="none" className="size-full text-gray-300">
<path
d="M0 -2L20 40L0 82"
stroke="currentcolor"
vectorEffect="non-scaling-stroke"
strokeLinejoin="round"
/>
</svg>
</div>
</>
) : null}
</li>
))}
</ol>
</nav>
)
}
Signup Page:
export default function Signup() {
const [ step, setStep ] = useAtom(stepsAtom);
const [signUp, setSignUp] = useAtom(signupFlow);
const router = useRouter();
const [toImmerSteps] = useImmerAtom(derivedStepsAtomImmer);
const updateStatus = produce((draft: Step, step: Step) => {
draft.status = step.status;
})
const handleClick = (event: React.FormEvent<HTMLButtonElement>, type: string) => {
event.preventDefault();
signUp.diabetesType = type;
step[0].status = 'complete';
setSignUp(signUp);
setStep((prev)=> prev.id === 1 ? ({...prev, status: step}) : prev);
updateStatus(toImmerSteps[0], step[0]);
router.push('/signup/step2');
};
return (
<center>
<div className="flex overflow-hidden rounded-lg bg-white shadow ">
<div className="px-8 py-8 sm:p-12 sm:pl-72">
<span className="font-bold">Select your diabetes type:</span>
<div className="pt-6 pb-4">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'TYPE1')}>Type 1</Button>
</div>
<div className="pb-4">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'TYPE2')}>Type 2</Button>
</div>
<div className="">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'PREDIABETIC')}>Prediabetic</Button>
</div>
</div>
</div>
</center>
)
}
I'm using NextJS 15 and Jotai. I'm tring to get withImmer to work on different pages (app directory) within a flow. What I mean is that I within a main directory called signup I have folders in it named step2, step3, etc.. I have one layout in the signup directory which has a progress bar that all sub-folders inherit from. My problem is that because the progress bar only renders once and not on each page the status of my progress bar doesn't get updated. I've tried using a store provider and that didn't work. I was hoping the immer would work but it doesn't either. Does anyone have any ideas on how to make this work? Below is some of the code I have.
export const stepsAtom = atom<Step[]>([
{ id: 1, name: 'Diabetes Type', href: '#', status: 'current' },
{ id: 2, name: 'Gender', href: '#', status: 'upcoming' },
{ id: 3, name: 'Age', href: '#', status: 'upcoming' },
{ id: 4, name: 'Height', href: '#', status: 'upcoming' },
{ id: 5, name: 'Weight', href: '#', status: 'upcoming' },
{ id: 6, name: 'Medical Conditions', href: '#', status: 'upcoming' },
{ id: 7, name: 'Physically Active', href: '#', status: 'upcoming' },
{ id: 8, name: 'Exercise', href: '#', status: 'upcoming' }
]);
export const derivedStepsAtomImmer = withImmer(stepsAtom);
Progress bar:
export default function ProgressBar() {
// const steps = initialSteps;
const [toImmerSteps] = useImmerAtom(derivedStepsAtomImmer);
return (
<nav aria-label="Progress">
<ol role="list" className="divide-y divide-gray-300 rounded-md border border-gray-300 md:flex md:divide-y-0">
{toImmerSteps.map((step, stepIdx) => (
<li key={step.name} className="relative md:flex md:flex-1">
{step.status === 'complete' ? (
<a href={step.href} className="group flex w-full items-center">
<span className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full bg-indigo-600 group-hover:bg-indigo-800">
<CheckIcon aria-hidden="true" className="size-6 text-white" />
</span>
<span className="ml-4 text-sm font-medium text-gray-900">{step.name}</span>
</span>
</a>
) : step.status === 'current' ? (
<a href={step.href} aria-current="step" className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-indigo-600">
<span className="text-indigo-600">{step.id}</span>
</span>
<span className="ml-4 text-sm font-medium text-indigo-600">{step.name}</span>
</a>
) : (
<a href={step.href} className="group flex items-center">
<span className="flex items-center px-6 py-4 text-sm font-medium">
<span className="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-gray-300 group-hover:border-gray-400">
<span className="text-gray-500 group-hover:text-gray-900">{step.id}</span>
</span>
<span className="ml-4 text-sm font-medium text-gray-500 group-hover:text-gray-900">{step.name}</span>
</span>
</a>
)}
{stepIdx !== step.length - 1 ? (
<>
{/* Arrow separator for lg screens and up */}
<div aria-hidden="true" className="absolute right-0 top-0 hidden h-full w-5 md:block">
<svg fill="none" viewBox="0 0 22 80" preserveAspectRatio="none" className="size-full text-gray-300">
<path
d="M0 -2L20 40L0 82"
stroke="currentcolor"
vectorEffect="non-scaling-stroke"
strokeLinejoin="round"
/>
</svg>
</div>
</>
) : null}
</li>
))}
</ol>
</nav>
)
}
Signup Page:
export default function Signup() {
const [ step, setStep ] = useAtom(stepsAtom);
const [signUp, setSignUp] = useAtom(signupFlow);
const router = useRouter();
const [toImmerSteps] = useImmerAtom(derivedStepsAtomImmer);
const updateStatus = produce((draft: Step, step: Step) => {
draft.status = step.status;
})
const handleClick = (event: React.FormEvent<HTMLButtonElement>, type: string) => {
event.preventDefault();
signUp.diabetesType = type;
step[0].status = 'complete';
setSignUp(signUp);
setStep((prev)=> prev.id === 1 ? ({...prev, status: step}) : prev);
updateStatus(toImmerSteps[0], step[0]);
router.push('/signup/step2');
};
return (
<center>
<div className="flex overflow-hidden rounded-lg bg-white shadow ">
<div className="px-8 py-8 sm:p-12 sm:pl-72">
<span className="font-bold">Select your diabetes type:</span>
<div className="pt-6 pb-4">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'TYPE1')}>Type 1</Button>
</div>
<div className="pb-4">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'TYPE2')}>Type 2</Button>
</div>
<div className="">
<Button className="w-24 bg-indigo-500 hover:bg-indigo-700" onClick={(evt) => handleClick(evt, 'PREDIABETIC')}>Prediabetic</Button>
</div>
</div>
</div>
</center>
)
}
Share
Improve this question
asked Mar 25 at 11:42
NewbieCoderNewbieCoder
951 silver badge11 bronze badges
1 Answer
Reset to default 0I figured out how to do it. I use searchParams in my progress bar like below to rerender the component.
useEffect(() => {
const param = searchParams.get('complete');
}, [searchParams]);
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744199419a4562809.html
评论列表(0条)