callstack / callstack/react-native-pager-view
NSInternalInconsistencyException crashes app
- 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