reactjs - Snabb uppdatering misslyckas vid dynamisk import av komponenter i Vite med React och TypeScript


Jag försöker skapa ett flerstegsformulär, jag har mina data i en separat fil för konstanter som detta

import { lazy } from 'react';

export const steps = [
  {
    id: 0,
    name: 'Personal Info',
    component: lazy(() => import('../components/PersonalInfo')),
  },
];

Jag skickar det till en anpassad hook i ett sammanhang

const dataSteps = useMultiStep(steps);

const { next, back, currentStep, isFirst } = dataSteps;

Detta är customhooken

import { useState } from 'react';
import { MultistepProps } from '../@types/Multiform';

const useMultiStep = (steps: MultistepProps[]) => {
  const [step, setStep] = useState(0);

  const isLast = step === steps?.length - 1;
  const isFirst = step === 0;

  const next = (): void => {
    if (isLast) return;
    setStep((current) => current + 1);
  };

  const back = (): void => {
    if (isFirst) return;
    setStep((current) => current - 1);
  };

  return {
    step,
    next,
    back,
    currentStep: steps[step],
    isFirst,
  };
};

export default useMultiStep;

Jag använder de dynamiska komponenterna här

import FormInterface from './interface/FormInterface';
import useApp from './hooks/useApp';
import { Suspense } from 'react';
function App() {
  const data = useApp();

  const { currentStep, next, back, isFirst } = data;

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    next();
  };

  return (
    <FormInterface>
      <form
        onSubmit={handleSubmit}
        className="flex flex-col h-full py-5 group"
        noValidate={true}
      >
        {currentStep.component && (
          <>
            <h1 className="text-3xl font-bold text-marineBlue">
              {currentStep?.name}
            </h1>

            <Suspense fallback={<div>Loading...</div>}>
              <currentStep.component /> //here
            </Suspense>

            <div
              className={`mt-4 sm:mt-auto flex ${
                isFirst ? 'justify-end' : 'justify-between'
              }`}
            >
              <button
                type="button"
                className={`hover:text-marineBlue font-bold text-coolGray py-2 px-5 rounded-md text-[13px] ${
                  isFirst ? 'hidden' : 'block'
                }`}
                onClick={back}
              >
                Go Back
              </button>
              <button
                type="submit"
                className="hover:bg-purplishBlue bg-marineBlue text-white py-2 px-5 rounded-md text-[12px] group-invalid:pointer-events-none group-invalid:opacity-30 self-end"
              >
                Next Step
              </button>
            </div>
          </>
        )}
      </form>
    </FormInterface>
  );
}

export default App;

Min vite-konfiguration är denna

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
});

Efter att ha försökt ALLT får jag fortfarande dessa fel, inte vid de första renderingarna utan när komponenten laddas om

App.tsx:7 Ohanterat TypeError: Kan inte destrukturera egenskapen 'currentStep' från 'data' eftersom den är null. vid App (App.tsx:7:11) vid renderWithHooks (react-dom.development.js:16305:18) vid mountIndeterminateComponent (react-dom.development.js:20074:13) vid beginWork (react-dom.development.js:21587:16) vid HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14) vid Object.invokeGuardedCallbackDev (react-dom.development.js:4213:16) vid invokeGuardedCallback (react-dom.development.js:4277:31) vid beginWork$1 (react-dom.development.js:27451:7) vid performUnitOfWork (react-dom.development.js:26557:12) vid workLoopSync (react-dom.development.js:26466:5)

Jag tror att det är ett HRM-problem eftersom det är som att ladda hela sidan istället för bara komponenten, och därför förloras tillstånden och informationen i useMultisteps förloras, men jag kan bara inte hitta ett sätt att få det att fungera, snälla hjälp mig eller lär mig ett bättre sätt att uppnå det jag försöker göra

Svar #1

Det verkar som att ditt tillstånd går förlorat när du uppdaterar komponenten (troligtvis eftersom useApp()-hooken returnerar null innan datan är redo).

  1. Försök att omsluta den stateful komponenten i en React memo(). På detta sätt bevaras komponentens tillstånd över HMR-uppdateringar.

t.ex. wrappa useApp-hooken i useMemo-hooken för att säkerställa att den bara anropas en gång:

const data = useMemo(() => useApp(), []);

För att sammanfatta kommer detta att säkerställa att useApp-hooken endast anropas en gång och att dess returvärde memoriseras, även om komponenten renderas om på grund av HMR.

  1. andra förslaget: försök att ändra din kod som nedan:

    const { currentStep, next, back, isFirst }=data ?? {};

Detta kommer att säkerställa att destruktureringen endast sker om dataobjektet inte är null.