recherche

Maison  >  Questions et réponses  >  le corps du texte

Rendu de plus d'erreurs de rendu précédentes sur le composant sans utiliser de hooks conditionnels

J'ai le composant suivant qui affiche un lien cliquable pour le téléchargement de fichiers

import { gql, useLazyQuery, useMutation } from '@apollo/client';
import { useEffect, useState } from 'react';
import type FileUpload from '@app/data/models/FileUpload';
import { ExternalLink } from '@app/mcui/components/atoms/business-process/shared/ExternalLink';
import { isNonEmptyString } from '@divvy-homes/utils';

export type Props = {
  uploadId: FileUpload['id'];
};

const FILE_UPLOAD_QUERY = gql`
  query ($id: UUID!) {
    getFileUpload(id: $id) {
      id
      fileName
      url
    }
  }
`;

const SIGN_FILE_MUTATION = gql`
  mutation ($url: String!) {
    signAdminUploadUrl(url: $url)
  }
`;
export const FileUploadLink = ({ uploadId }: Props) => {
  const [fileUrl, setFileUrl] = useState<string>();
  const [fileName, setFileName] = useState<string>();
  const [getFileData] = useLazyQuery<{
    getFileUpload: {
      url: string;
      fileName: string;
    };
  }>(FILE_UPLOAD_QUERY, {
    onError: console.error,
    onCompleted: (data) => {
      setFileName(data.getFileUpload.fileName);
      setFileUrl(data.getFileUpload.url);
    },
    variables: {
      id: uploadId,
    },
  });

  useEffect(() => {
    void getFileData({ variables: { uploadId } });
  }, [getFileData, uploadId]);

  const [createSignedDocumentUrl] = useMutation<{ signAdminUploadUrl: string }>(
    SIGN_FILE_MUTATION,
    {
      onError: console.error,
      onCompleted: (urlData) => {
        const signedUrl = urlData.signAdminUploadUrl;
        window.open(signedUrl, '_blank', 'noreferrer');
      },
    },
  );

  return isNonEmptyString(fileUrl) ? (
    <ExternalLink
      onClick={() => void createSignedDocumentUrl({ variables: { url: fileUrl } })}
      text={fileName ?? ''}
    />
  ) : undefined;
};

Chaque fois que je télécharge un fichier à l'aide de ce composant, j'obtiens une erreur de réaction渲染的钩子比上次渲染期间更多。. React indique que l'ordre des hooks a changé comme suit

client.js:1 Warning: React has detected a change in the order of Hooks called by BusinessProcessDetails. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

   Previous render            Next render
   ------------------------------------------------------
 1. useContext                 useContext
 2. useContext                 useContext
 3. useContext                 useContext
 4. useContext                 useContext
 5. useRef                     useRef
 6. undefined                  useState

En regardant mon code, je n'arrive pas à comprendre pourquoi cette erreur se produit. React dit que c'est la première ligne du composant qui appelle useState qui provoque l'erreur, mais cela n'a aucun sens pour moi. L'appel d'un hook réactif sans conditions provoque cela, et la première ligne du composant qui génère cette erreur ne correspond pas à l'ordre dans lequel le hook a changé.

J'utilise React 18.2.0, TypeScript 4.9.5

P粉331849987P粉331849987443 Il y a quelques jours594

répondre à tous(1)je répondrai

  • P粉148434742

    P粉1484347422023-09-10 20:47:31

    Il s'avère que le problème réside dans la façon dont le composant est appelé. Le rendu du composant parent FileUploadLink ressemble à ceci

    export const MyComponent = ({ fileUpload }: MyProps) => {
      const values = [
        {
          label: 'MyLabel',
          value: fileUpload ? FileUploadLink({ uploadId: fileUpload }) : undefined,
        },
      ];
    
      return (
        <>
          {values.map((l, v) => {
            <div>{l}</div>;
            {
              v;
            }
          })}
        </>
      );
    };

    Le correctif consiste à envelopper le composant dans une balise, c'est-à-dire

    const values = [
        {
          label: 'MyLabel',
          value: fileUpload ? <FileUploadLink uploadId={fileUpload} /> : undefined,
        },
      ];

    répondre
    0
  • Annulerrépondre