Компонент React не реагирует на наблюдаемые данные mobx

Я использую mobX для моего собственного проекта React. Обратите внимание на этот класс магазина:

class Birds {
    @observable listOne = [];
    @observable fetchingListOne = false;
    @observable fetchErrorOne = '';

    @action setListOne = () => {
        this.fetchingListOne = true;
        api.getList()
            .then((data) => {
                this.listOne.replace(data);
                this.fetchingListOne = false;
            })
            .catch((error) => {
                this.fetchingListOne = false;
                this.fetchErrorOne = error;
            });
    };
}

И это компонент реакции:

@inject('BirdStore') @observer
export default class Flat extends React.Component {
    componentDidMount() {
        this.props.BirdStore.setListOne();
    }

    _renderHeader = () => {
        return <Text style={styles.listHeaderText}>
            Hello {this.props.BirdStore.listOne.length} is {this.props.BirdStore.fetchingListOne.toString()}
            </Text>;
    };

    _renderItem = ({item}) => {
        return <Text style={styles.item}>{item.name}</Text>
    };

    _renderFooter = () => {
        if (this.props.BirdStore.fetchingListOne) {
            return <ActivityIndicator/>
        }
        else {
            return null
        }
    };

    render() {
        const dataSource = this.props.BirdStore.listOne.slice();

        return (
                <View style={styles.container}>
                    <Text>Fetching: {this.props.BirdStore.fetchingListOne.toString()}</Text>
                    <FlatList
                        style={styles.listContainer}
                        ListHeaderComponent={this._renderHeader}
                        data={dataSource}
                        renderItem={this._renderItem}
                        keyExtractor={(item, i) => item.id}
                        ListFooterComponent={this._renderFooter}
                    />
                </View>
        )
    }
}

Сверху мне кажется, что:

  1. Когда компонент Flat монтируется, он вызывает метод хранилища setListOne().
  2. setListOne() устанавливает для fetchingListOne значение true и выполняет вызов API.
  3. На стороне компонента, когда fetchingListOne имеет значение true, отображается ActivityIndicator, а в ListHeaderComponent должно отображаться значение true.
  4. На стороне магазина после успешного / неудачного ответа он устанавливает fetchingListOne в значение false.
  5. Наконец, на стороне компонента, поскольку для fetchingListOne установлено значение false, ActivityIndicator не должен отображаться, а в ListHeaderComponent должен отображаться false.

Однако это не то, что происходит. Здесь, когда вызывается метод setListOne(), после того, как он устанавливает для fetchingListOne значение true, компонент не реагирует на изменения, сделанные после вызова api. И ActivityIndicator продолжает отображаться, а в ListHeaderComponent его отображение истинно.

Что я здесь делаю не так? Не могли бы вы мне помочь. Спасибо

Обновить

Я добавил текстовый компонент перед FlatList. Добавление компонента Text или ведения журнала консоли внутри метода рендеринга класса компонента заставляет FlatList реагировать на изменения. Но я не знаю, почему это происходит.


person Benjamin Smith Max    schedule 14.08.2017    source источник
comment
Не могли бы вы попробовать использовать mobx.useStrict(), чтобы узнать, решит ли это вашу проблему? Это означает использование геттеров и сеттеров для наблюдаемых значений, особенно fetchingListOne   -  person Christopher Chiche    schedule 15.08.2017
comment
@ChristopherChiche Я попытался разместить mobx.useStrict(true) в store.js, где присутствует класс Birds. Но это дало мне ошибку: ... Пожалуйста, заключите код в action, если это изменение предполагается. Пытался изменить: [email protected]]. Поэтому я поместил useStrict(); в @action setListOne. Он не выдает ошибок, но имеет ту же проблему; компонент FlatList не реагирует на эти изменения, как должно быть.   -  person Benjamin Smith Max    schedule 15.08.2017


Ответы (1)


Проблема, с которой вы здесь столкнулись, скорее всего, заключается в том, что, хотя Flat является observer компонентом, FlatList нет (в конце концов, это встроенный компонент). В этой настройке _renderFooter и другие части визуализируются render из FlatList, но не FlatList. Следовательно, они не являются частью жизненного цикла Flat, а FlatList и поэтому не отслеживаются Mobx.

Есть два способа исправить это, оба довольно простые:

1) объявить _renderItem как компонент наблюдателя:

_renderItem = observer(({item}) =>
    <Text style={styles.item}>{item.name}</Text>
);

2) используйте встроенный анонимный компонент Observer:

_renderItem = ({item}) => 
    <Observer>{
        () => <Text style={styles.item}>{item.name}</Text>}
    </Observer>
person mweststrate    schedule 15.08.2017
comment
Да, я думаю, что проблема в том, что я добавил компонент Text над FlatList, и он действительно реагирует на изменения, также, это заставляет весь FlatList работать идеально (обновил код, пожалуйста, посмотрите метод рендеринга класса). В любом случае, первый метод выдает ошибку [TypeError: невозможно вызвать класс как функцию]. И второй метод в основном делает то же самое; он отображает весь список после выборки. - person Benjamin Smith Max; 15.08.2017