React-native: SectionList doesn't work right with MobX

Created on 24 Jul 2017  Â·  7Comments  Â·  Source: facebook/react-native

I am using SectionList with MobX (React-MobX). Then I get lots of warnings from mobx says: [mobx.array] Attempt to read an array index(2) that is out of bounds (2). Please check length first. Out of bound indices will not be tracked by MobX (50 times) and [mobx.array] Attempt to read an array index(4) that is out of bounds (4). Please check length first. Out of bound indices will not be tracked by MobX (6 times) with the code below.
I found it may be a bug for SectionList, cause if I commented SectionList rows, it's ok.

Code here:

import React from 'react';
import {
    View,
    Text,
    SectionList,
    StyleSheet,
} from 'react-native';
import {observer,inject} from 'mobx-react';
import {observable,autorun,action} from 'mobx';

let data = [
            {month: '五月', data: [{
                key:"1",
                date:"27æ—¥",
                time:"08:42"
            },{
                key:"2",
                date:"28r",
                time:"08:42"
            }]},
            {month: '六月', data: [{
                key:"3",
                date:"21æ—¥",
                time:"08:42"
            },{
                key:"4",
                date:"21r",
                time:"18:42"
            },{
                key:"5",
                date:"21r",
                time:"18:42"
            },{
                key:"6",
                date:"21r",
                time:"18:42"
            }]},
        ];
@observer
export default class List extends React.Component{
    @observable refreshing = false;
    @observable pagination = {
        page:1,
        pageSize:10,
    }
    @observable listData = [];
    @action refresh = ()=>{
        console.warn("refreshed");
        this.pagination.page = 1;
        this.refreshing = true;
        setTimeout(action(()=>{
            this.refreshing = false;
            this.listData=data;
        }),500);
    }
    @action loadMore = ({distanceFromEnd})=>{
    }
    componentDidMount(){
        this.refresh();
    }
    render(){
        return (
            <View style={styles.flex1}>
                <Text>{JSON.stringify(this.listData)}</Text>
                 <SectionList
                    onRefresh={this.refresh}
                    refreshing={this.refreshing}
                    onEndReached={this.loadMore}
                    renderSectionHeader={({section})=><Text>{section.month}</Text>}
                    renderItem={({item})=><Text>1</Text>}
                    sections={this.listData}
                />
            </View>
        )
    }
}

const styles = StyleSheet.create({
    flex1:{
        flex:1,
    },
})

Environment

  1. react-native -v:
    react-native-cli: 2.0.1
    react-native: 0.46.0
  2. node -v:
    v7.10.0
  3. npm -v:
    3.10.9
    mobx: 3.2.1 , mobx-react: 4.2.2
  • Target Platform: Android (IOS not tested yet)
  • Development Operating System: Win10
Locked

Most helpful comment

@coolguy001tv I ran into this same issue and @brentvatne is correct, you need to slice() your nested arrays to get plain arrays instead of observable arrays. So this.listData[0].data is not compatible with Section.data, whereas this.listData[0].data.slice() will work. See mobx best practices.

All 7 comments

hello! you might want to post this to mobx issues as the warnings are coming from there. SectionList/FlatList require that you pass in a plain array, there should be some way for mobx to let you do that. see: https://facebook.github.io/react-native/docs/flatlist.html#data / https://facebook.github.io/react-native/docs/sectionlist.html#sections

@coolguy001tv I ran into this same issue and @brentvatne is correct, you need to slice() your nested arrays to get plain arrays instead of observable arrays. So this.listData[0].data is not compatible with Section.data, whereas this.listData[0].data.slice() will work. See mobx best practices.

@stephenlaughton Thank you so much. It works for me.
I am newbie to mobx. And I've just missed the mobx best practices.

@stephenlaughton
@coolguy001tv

im still getting a lot of warnings even if i .slice(), the sectionList is showing ok :/

@CodeXtinction you may not do it right. Here's my example (pseudo code, just for instruction):

let listData = [
            {month: '五月', data: [{
                key:"1",
                date:"27æ—¥",
                time:"08:42"
            },{
                key:"2",
                date:"28r",
                time:"08:42"
            }]},
            {month: '六月', data: [{
                key:"3",
                date:"21æ—¥",
                time:"08:42"
            },{
                key:"4",
                date:"21r",
                time:"18:42"
            },{
                key:"5",
                date:"21r",
                time:"18:42"
            },{
                key:"6",
                date:"21r",
                time:"18:42"
            }]},
        ];


//
@computed get formattedList(){
        return this.listData.map((v)=>{
            return {
                month: v.month,
                data: v.data.slice(),//You need to slice data
            }
        }).slice();// And slice the listData
    }
//
<SectionList
                    ...
                    sections={this.props.BillStore.formattedList}
                />

If you can't understand , you can try pasting your code.

@observable.shallow data = [...]

Thanks guys for answer on this question

Was this page helpful?
0 / 5 - 0 ratings