admin管理员组文章数量:1400211
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]);
本文标签: NextJSJotai trying to get immer to work on several different pagesStack Overflow
版权声明:本文标题:NextJS, Jotai trying to get immer to work on several different pages - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744199418a2594893.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论