I am rendering a restaurant menu and I display it in a ScrollView
.
For some reason, first time I render the screen, everything works perfectly. BUT if I leave the screen and navigate again to it, and I console.log
this.state.catTitlesXVals
and this.state.catTitlesWidthsSorted
they have the default values which are initialised in the state. I use these functions so I can get this effect you can see below of the categories:
I do not understand why the second time I navigate to the screen and it gets mounted, the functions I have below do not update the state correctly.
I am really lost here, any help would be much appreciated. Thank you in advance :)
componentDidUpdate() { // since onLayout for some (weird) reason returns the widths in an unsorted manner, // we will sort them since we know that x has to be always in ascending order and // we can use that as a reference if (this.state.catTitlesXvals.length == this.state.numCategories && !this.state.catTitlesWidthsSorted) { this.setState({ catTitlesWidthsSorted: true }, () => { var temp = []; var xvals = this.state.catTitlesXvals; var i; for (i = 0; i < this.state.catTitlesXvals.length; i++) { var index; var obj = this.state.catTitlesWidthsRef[i]; index = xvals.indexOf(Number(Object.keys(obj)[0])); temp[index] = obj[xvals[index].toString()] } this.setState({ catTitlesWidths: temp, translateWidth: new Animated.Value(temp[0]) }) }) } } _onLayoutCategories = ({ nativeEvent: { layout: { x, y, width, height } } }) => { this.setState(prevState => ({ categoryYvals: [...prevState.categoryYvals, y].sort(function (a, b) { return a - b }) })) }; _onLayoutCatTitles = ({ nativeEvent: { layout: { x, y, width, height } } }) => { this.setState(prevState => ({ catTitlesWidths: [...prevState.catTitlesWidths, width], catTitlesXvals: [...prevState.catTitlesXvals, x].sort(function (a, b) { return a - b }), catTitlesWidthsRef: [...prevState.catTitlesWidthsRef, { [x]: width }] })) }; handleScroll = (event) => { var y = event.nativeEvent.contentOffset.y for (let i = 0; i < this.state.categoryYvals.length; i++) { if (y > this.state.categoryYvals[i] && y < this.state.categoryYvals[i + 1]) { let translateValueX = this.state.catTitlesXvals[i]; let translateValueW = this.state.catTitlesWidths[i]; Animated.parallel([ Animated.timing( this.state.translateX, { toValue: translateValueX, duration: 75, } ), Animated.timing( this.state.translateWidth, { toValue: translateValueW, duration: 50, } ) ]).start() } } }render() { return (<View style={styles.container}> ...<ScrollView stickyHeaderIndices={[0]} ref={(node) => this.scroll = node} onScroll={this.handleScroll} scrollEventThrottle={1}><View style={{ flex: 1, backgroundColor: 'white', paddingTop: 45 }}> ...<ScrollView style={{ backgroundColor: 'white', borderBottomColor: 'orange', borderBottomWidth: 1 }} horizontal={true} showsHorizontalScrollIndicator={false} ref={(node) => this.scrollTitles = node}><View style={{ flexDirection: 'row', alignItems: 'center', height: 50 }}> {getCatTitles(this.props.route.params['menu'])}</View><Animated.View style={[styles.highlight, { left: this.state.translateX, width: this.state.translateWidth }]}></Animated.View></ScrollView></View> {DisplayMenu(this.props.route.params['menu'], this)} ...function DisplayMenu(MenuText, defaultThis) { var menu = JSON.parse(MenuText); var CategoriesNum; CategoriesNum = menu.length; var i; var components = []; for (i = 1; i < CategoriesNum + 1; i++) { let catTitle = menu[i - 1][i.toString()]["catTitle"] var temp = (<View style={styles.category} key={'cat_'+ i} onLayout={defaultThis._onLayoutCategories}><Text style={styles.catTitle}>{catTitle}</Text><View style={styles.catItems}> {generateItemC(menu, i, defaultThis)}</View></View>); components[i] = temp; } return (<View>{components}</View> )}