Des*_*amo 1 javascript reactjs react-hooks
我有一个问题,我有著名的反应错误:未捕获(承诺)错误:渲染的钩子比预期少。这可能是由于意外的提前退货声明造成的。
\n但我正在寻找问题,但没有找到,因为我认为我的钩子顺序很好,但事实并非如此......您知道错误在哪里吗?
\n谢谢
\nimport { useNavigate, Link, useParams } from 'react-router-dom';\n import { useEffect, useState, useCallback, useMemo } from 'react';\n import { Formik } from 'formik';\n import { useIntl, FormattedMessage } from 'react-intl';\n import { useQuery, gql, useMutation } from '@apollo/client';\n import { sub } from 'date-fns';\n \n import {\n Text,\n Button,\n TextField,\n DateField,\n Banner,\n Loader,\n Icon,\n } from '@customer-portal/components';\n \n import { StandardField } from '../../components/FormikFields';\n import { useError } from '../../hooks/useError';\n import { toISODate, toStartOfDay } from '../../utils/date';\n import { useFilteredContracts } from '../../components/ContractsFilter';\n \n export function MeterReadingToEnterForm() {\n const [date, setDate] = useState();\n const [forceResult, setForceResult] = useState(false);\n const [successBanner, setSuccessBanner] = useState(false);\n let navigate = useNavigate();\n let { serial } = useParams();\n const intl = useIntl();\n const contract = useFilteredContracts();\n const initialValues = {};\n const getError = useError(error);\n \n useEffect(() => {\n return () => {\n navigate('/meter-reading');\n };\n }, [contract.id]);\n \n const {\n loading,\n data: queryData,\n error,\n refetch,\n } = useQuery(QUERY, {\n notifyOnNetworkStatusChange: true,\n fetchPolicy: 'network-only',\n variables: {\n date: toStartOfDay(Date.now()),\n contractId: contract.id,\n },\n });\n \n const [enterMeterReading, { loading: enterLoading, error: enterError }] =\n useMutation(MUTATION_QUERY, {\n onCompleted: () => setSuccessBanner(true),\n });\n \n useEffect(() => {\n refetch({ variables: { date: toStartOfDay(date) } });\n }, [date]);\n \n if (error) {\n return (\n <Banner data-test="BannerNoContracts" type="error" iconName="Alert">\n <Text>{getError()}</Text>\n </Banner>\n );\n }\n \n if (enterError) {\n return (\n <Banner type="error" iconName="Alert">\n <Text>{getError()}</Text>\n </Banner>\n );\n }\n \n const formattedValues = (valeur) => {\n let array = Object.keys(valeur).map((key) => ({\n id: key,\n result: valeur[key],\n }));\n return array;\n };\n \n const handle = useCallback((values) => {\n mutationQuery({\n variables: {\n data: {\n serial: serial,\n results: formattedValues(values),\n },\n Id: id,\n },\n refetchQueries: ['newQuery'],\n });\n });\n \n return (\n <div sx={{ display: 'flex', flexDirection: 'column', width: '100%', p: 2 }}>\n <div sx={{ display: 'flex', pt: 6, width: '100%' }}>\n <Icon\n sx={{ display: 'flex', alignItems: 'center', m: 3 }}\n color="primary"\n name="Counter"\n size="large"\n />\n <Text weight="bold" sx={{ display: 'flex', alignItems: 'center' }}>\n <FormattedMessage\n defaultMessage="N\xc2\xb0 {number}"\n values={{\n number: `${serial}`,\n }}\n />\n </Text>\n </div>\n {successBanner && (\n <div sx={{ mb: 4 }}>\n <Banner\n iconName="SuccessOutline"\n type="success"\n >\n <Text>\n <FormattedMessage\n defaultMessage="Done"\n />\n </Text>\n </Banner>\n </div>\n )}\n <div sx={{ display: 'flex', justifyContent: 'flex-start', py: 2 }}>\n <DateField\n name="datefoield"\n value={date || Date.now()}\n onChange={(date) => setDate(date)}\n required={true}\n label={intl.formatMessage({\n defaultMessage: 'Date du relev\xc3\xa9',\n })}\n defaultSelected={date}\n disabledDays={[\n {\n before: sub(new Date(toISODate(Date.now())), {\n days: 60,\n }),\n },\n {\n after: new Date(Date.now()),\n },\n ]}\n />\n </div>\n {enterLoading && <Loader type="radiance" overlay={true} />}\n {loading ? (\n <Loader sx={{ mx: [0, 11] }} />\n ) : (\n <Formik\n onSubmit={handleEnterMeterReading}\n initialValues={initialValues}\n >\n {({ values, handleSubmit }) => {\n const query = useMemo(() => {\n return queryDatafind(\n (serialNumber) => serialNumber === serial\n );\n }, [queryData]); \n \n return (\n <form\n noValidate={true}\n onSubmit={handleSubmit}\n >\n <div\n sx={{\n display: 'flex',\n flexWrap: 'wrap',\n width: '100%',\n py: 2,\n }}\n >\n {query.map((value) => (\n <div sx={{ mr: 4 }}>\n <StandardField\n as={TextField}\n id={id}\n label={label}\n required\n name={id}\n size="standard"\n type="number"\n variant="standard"\n />\n </div>\n ))}\n </div>\n <div sx={{ display: 'flex', py: 6 }}>\n <Link to="/">\n <Button\n sx={{ my: 4, mr: 4 }}\n startIcon="ErrorOutline"\n size="standard"\n variant="outlined"\n >\n {intl.formatMessage({\n defaultMessage: 'Annuler',\n })}\n </Button>\n </Link>\n <Button\n sx={{ whiteSpace: 'nowrap', my: 4 }}\n startIcon="SuccessOutline"\n size="standard"\n type="submit"\n disabled={loading}\n >\n {loading\n ? intl.formatMessage({\n defaultMessage: 'loading',\n })\n : intl.formatMessage({\n defaultMessage: 'Validate',\n })}\n </Button>\n </div>\n </form>\n );\n }}\n </Formik>\n )}\n </div>\n );\n }\n \n\n-- GRAPHQL REQUEST---\nRun Code Online (Sandbox Code Playgroud)\n
问题是您useCallback在某些if条件之后调用可能会return过早。您可以删除该useCallback调用(只需handle在每次渲染时设置一个新的函数闭包),或者将调用移至suseCallback之上if ... return。
| 归档时间: |
|
| 查看次数: |
6587 次 |
| 最近记录: |