callstack / callstack/react-native-pager-view

NSInternalInconsistencyException crashes app

Ouverte
#507 6 commentaires 3 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
TypeScript
Étoiles
3.4k
Forks
476
Merge moyen
10 j 21 h
PR mergées (30 j)
2

Description

## 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 (







)
})}


)
}
```

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Commencez par la référence PagerView du composant DateSlider et l’appel asynchrone à setPage, puis reproduisez le problème sur iOS avec plus de 20 pages et dateTicker défini sur 100 jours au lieu de 10. Comparez le nombre de pages générées et le timing de la navigation ; le travail est terminé lorsque la navigation vers la page sélectionnée ne déclenche plus NSInternalInconsistencyException.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
ios, react-native, typescript
Domaine
mobile
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.