callstack / callstack/react-native-pager-view

NSInternalInconsistencyException crashes app

Aperta
#507 6 commenti 3 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
TypeScript
Stelle
3.4k
Fork
476
Merge medio
10g 21h
PR unite (30g)
2

Descrizione

## Environment

iOS

## Description

I have some fairly simple code that populates pages and then navigates to one of them. For some reason, if I am generating more than 20/30 pages on iOS, the app crashes with:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unexpected view controller: '

## Reproducible Demo

I populate maybe 20 pages, and then elsewhere in the app, asynchronously navigate to a page somewhere towards the end (but after the pages in theory have been populated). I can see for a split second that it's trying to land on a page that doesn't yet exist, then it crashes. I guess that it's trying to access this screen before it has time to generate it. Oddly, using a setTimeout to access the page does not help. I call the page with `setPage` on the ref.

The code of the component in question:

```
type Props = {
// Should always be in order
dates: SliderDate[]
onDateSelect: (date: Date) => void
}

function sliceIntoChunks(arr: any[], chunkSize: number) {
const res = []
for (let i = 0; i < arr.length; i += chunkSize) {
const chunk = arr.slice(i, i + chunkSize)
res.push(chunk)
}

return res
}

export const DateSlider = (props: Props) => {
const [weeks, setWeeks] = useState([])

const getWeeks = (dates: SliderDate[]): SliderDate[][] => {
const weekResult: SliderDate[] = []

/// Fill with blank dates
const dateTicker = new Date()
dateTicker.setHours(0, 0, 0, 0)
dateTicker.setDate(dateTicker.getDate() - 100) // <--- breaks it
// dateTicker.setDate(dateTicker.getDate() - 10) // <- this one is ok

// find closest monday
while (dateTicker.getDay() !== 1) {
dateTicker.setDate(dateTicker.getDate() + 1)
}

console.log("got here")
for (let i = -10; i < 30; i++) {
// console.log(dateTicker.getDay())
if (dateTicker.getDay() !== 0 && dateTicker.getDay() !== 6) {
weekResult.push({
date: new Date(dateTicker),
selected: false,
recurring: false,
ordered: false,
disabled: true,
})
}

dateTicker.setDate(dateTicker.getDate() + 1)
}

while (weekResult.length % 5 !== 0) {
console.log("got here2", weekResult.length)

if (dateTicker.getDay() !== 0 && dateTicker.getDay() !== 6) {
weekResult.push({
date: new Date(dateTicker),
selected: false,
recurring: false,
ordered: false,
disabled: true,
})
}

dateTicker.setDate(dateTicker.getDate() + 1)
}

/// Overwrite with dates from props
for (const date of props.dates) {
const realIndex = weekResult.findIndex(day => {
return day.date.toISOString() === date.date.toISOString()
})

weekResult[realIndex] = date
}

return sliceIntoChunks(weekResult, 5)
}

useEffect(() => {
const newWeeks = getWeeks(props.dates)
setWeeks(newWeeks)

const idx = newWeeks.findIndex(week => {
return !!week.find(day => day.selected)
})
if (idx < newWeeks.length) {
setTimeout(() => {
// @ts-ignore
pagerRef.current!.setPage(idx)
}, 500)
}
}, [props.dates])
const pagerRef = useRef(null)

return (


{weeks.map(week => {
return (







)
})}


)
}
```

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con il ref PagerView del componente DateSlider e la chiamata asincrona a setPage, quindi riproduci il problema su iOS con più di 20 pagine e reimposta dateTicker a 100 giorni anziché 10. Confronta il numero di pagine generate e i tempi di navigazione; il lavoro è completato quando la navigazione alla pagina selezionata non genera più NSInternalInconsistencyException.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
ios, react-native, typescript
Ambito
mobile
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Da chiarire
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.