Отрисовано меньше крючков, чем ожидалось. Это может быть вызвано случайным заявлением о досрочном возврате

#javascript #reactjs

Вопрос:

Я получаю эту ошибку при запуске setState внутри пользовательского крючка реакции. Я не уверен, как это исправить, может ли кто-нибудь показать мне, что я делаю неправильно. Он получает ошибку, когда попадает в строку handleSetReportState (). Как я должен устанавливать состояние отчета изнутри крючка?

пользовательский крюк опроса useinterval

 export function usePoll(callback: IntervalFunction, delay: number) {
const savedCallback = useRef<IntervalFunction | null>()

useEffect(() => {
    savedCallback.current = callback
}, [callback])

useEffect(() => {
    function tick() {
        if (savedCallback.current !== null) {
            savedCallback.current()
        }
    }
    const id = setInterval(tick, delay)
    return () => clearInterval(id)
}, [delay])
}
 

React FC

 const BankLink: React.FC = ({ report: _report }) =>  {

const [report, setReport] = React.useState(_report)

if ([...Statues].includes(report.status)) {
    
    usePoll(async () => {
        const initialStatus = _report.status
        const { result } = await apiPost(`/links/search` });
        const currentReport = result.results.filter((item: { id: string; }) => item.id === _report.id)

        if (currentReport[0].status !== initialStatus) {
            handleSetReportState(currentReport[0])
            console.log('status changed')
        } else {
            console.log('status unchanged')
        }
    }, 5000)
}
... rest
 

Ответ №1:

Это потому, что вы поставили usePoll условие «если», понимаете https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

Вы можете поместить условие в обратный вызов

 usePoll(async () => {
    if ([...Statues].includes(report.status)) {
        const initialStatus = _report.status
        const { result } = await apiPost(`/links/search` });
        const currentReport = result.results.filter((item: { id: string; }) => item.id === _report.id)

        if (currentReport[0].status !== initialStatus) {
            handleSetReportState(currentReport[0])
            console.log('status changed')
        } else {
            console.log('status unchanged')
        }
    }
}, 5000)
 

И если задержка повлияет report.status , используйте ref для хранения report.status и считывания значения ref в обратном вызове.