mobx: array.map () не является функцией

Я создал магазин, используя mobx следующим образом:

import {extendObservable} from 'mobx';

class InfluencerFeedStore {
    constructor() {
        extendObservable(this, {
            data: []
        });
    }

    setData(items = []) {
        this.data = items;
    }
}

export default new InfluencerFeedStore();

Затем я наблюдаю за этим магазином в своем представлении React:

import React from 'react';
import {observer} from 'mobx-react';
import FeedItem from './FeedItem';
import InfluencerFeedStore from '../../core/stores/InfluencerFeed';

import './style.css';

const generateItems = () => {
    return InfluencerFeedStore.data.map((item, i) => (
        <FeedItem key={`feeditem-${i}`} {...item} />
    ));
};

const Feed = () => (
    <div className="Feed vertical-scroll-flex-child">
        {generateItems()}
    </div>
);

export default observer(Feed);

При первом рендеринге мой Feed вид работает нормально (хотя в массиве InfluencerFeedStore.data нет элементов).

Если позже я загружу элементы, вызвав InfluencerFeedStore.setData(), React попытается правильно повторно отрендерить представление Feed (потому что он заметил, что наблюдаемое mobx обновлено) ... но я получаю сообщение об ошибке, что InfluencerFeedStore.data.map is not a function.

Прочитав mobx документы, я понял, что переназначение моего свойства data проблематично, потому что это массив (тогда как другие типы данных, такие как строки, «просто работают»). Может ли кто-нибудь сказать мне, что я здесь делаю не так?


person arthurakay    schedule 01.12.2016    source источник
comment
Исключительно для моего собственного назидания, вы, кажется, получаете доступ к этим данным val статическим образом, а не из экземпляра класса (данные инициализируются в конструкторе). Это нормально? ObservableFeed будет представлять экземпляр.   -  person Tim Consolazio    schedule 01.12.2016
comment
действительно, конструктор никогда не вызывается, поэтому это не сработает. Сначала должен быть создан экземпляр Store   -  person mweststrate    schedule 01.12.2016


Ответы (2)


Получается, что у меня было две проблемы:

  1. Мне нужно было использовать метод replace() для перезаписи наблюдаемого массива, а не пытается полностью переназначить новое значение
  2. На самом деле я не передавал массив в свой setData() метод; поэтому я получил ошибку "карта не функция"

Должно получиться так:

import {extendObservable} from 'mobx';

class InfluencerFeedStore {
    constructor() {
        extendObservable(this, {
            data: []
        });
    }

    setData(items = []) {
        this.data.replace(items);
    }
}

export default new InfluencerFeedStore();
person arthurakay    schedule 01.12.2016

Проблема в том (я думаю, на основании моего комментария) вы не обращаетесь к «данным» из экземпляра класса, вы обращаетесь к нему статически, поэтому конструктор класса никогда не запускается, а «данные» никогда не инициализируются. «ObservableFeed» - это экземпляр.

person Tim Consolazio    schedule 01.12.2016
comment
Я не думаю, что это правильно. В моем файле магазина единственное, что я экспортирую, - это я export default ObservableFeed - поэтому, когда я import InfluencerFeedStore, он ссылается на тот же объект экземпляра (он просто переименован). Если я полностью не понимаю ES2015 (что возможно!) - person arthurakay; 01.12.2016
comment
Хм ... но тогда разве вы не захотели бы импортировать экспортированный член (который был бы экземпляром)? Мое понимание модулей ES6 немного шаткое, поскольку используемые мной компоновщики не поддерживают их. Но из того, что вы говорите, вы можете экспортировать одно (ObervableFeed), импортировать другое (InfluencerFeedStore) и тем самым каким-то образом неявно получить поведение ObervableFeed? - person Tim Consolazio; 01.12.2016
comment
Я нашел это, что кажется гелеобразным: может быть только один экспорт по умолчанию. Это в основном используется, когда вы экспортируете одну вещь, например класс, или одну функцию, которую вы ожидаете использовать без какой-либо дополнительной поддержки. Когда вы импортируете модуль с экспортом по умолчанию, используйте import d from c. Означает ли это, что нужно импортировать ObservableFeed из ./etc/InfluencerFeed? - person Tim Consolazio; 01.12.2016
comment
Верно ... так что все, что я export (ObservableFeed), можно явно переименовать во время import (ObservableFeed ››› SomeNewName). Обычно для простоты используется одно и то же имя переменной, но я так понимаю. - person arthurakay; 01.12.2016
comment
Я также мог бы просто сделать это: export default new InfluencerFeedStore(); (РЕДАКТИРОВАТЬ: я обновил свой код, чтобы сделать это для простоты) - person arthurakay; 01.12.2016
comment
Хм ... Думаю, сейчас я бы попробовал импортировать ObservableFeed из вашего класса. Если вы хотите переименовать его в своем импорте, продолжайте, но в остальном мое первоначальное предположение (исходя из работы с другими модульными системами) заключается в том, что здесь чего-то не хватает, поэтому вы на самом деле не используете ObservableFeed. Отличный разговор здесь. Принесите ES6! - person Tim Consolazio; 01.12.2016