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