Можно ли передавать данные в withTracker напрямую из его компонента более низкого порядка?

Я работаю в существующей кодовой базе, которая использует комбинацию React, Meteor и response-meteor-data.

Все шло относительно хорошо, пока я не попытался внедрить функцию поиска с помощью withTracker, React Select, и функциональность подписки Meteor.

import { CollectionAPI } from '../arbitrary_meteormongo_collection';

export const WriteableConnectionToCollection = withTracker(props => {
    let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', SEARCH_TEXT_HERE); 
    let isLoading = connection.ready();

    return {
        ...props,
        isLoading: isLoading,
        collection: CollectionAPI.find().fetch()
    }
})(PRESENTATIONAL_COMPONENT);

Я погуглил и увидел, что распространенным решением для получения данных в Meteor.subscribe является использование таких вещей, как параметры URL, хотя, поскольку я работаю в существующей кодовой базе, это изменение также необходимо будет реализовать в разных местах.

Другой способ, который я нашел, - передать значение поля ввода родительскому компоненту, отслеживая состояние поля ввода в состоянии родительского компонента, хотя это явно нарушает принцип разделения задач:

Родительский компонент

export const ParentComponent = React.createClass({
    getInitialState() {
        return {
            inputFieldValue: undefined
        }
    },

    onChange(change) {
        this.setState(inputFieldValue);
    },

    render() {
        return (
            <Search 
                onChange={this.onChange}
                inputFieldValue={this.state.inputFieldValue}
            />
    }
}

withTracker HOC

import { CollectionAPI } from '../arbitrary_meteormongo_collection';

export const WriteableConnectionToCollection = withTracker(props => {
    let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', this.props.inputFieldValue); 
    let isLoading = connection.ready();

    return {
        ...props,
        isLoading: isLoading,
        collection: CollectionAPI.find().fetch()
    }
});

Компонент InputField

import { WriteableConnectionToCollection } from './connections/writeableconnection.js';

const InputFieldComponent = React.createClass({

    render() {
        <InputField 
            onInputChange={this.props.onChange}
        />
    }
}

export default WritableConnectionToCollection(InputFieldComponent);

Это единственный способ сделать что-то с этой конкретной комбинацией пакета/фреймворка или есть более простой способ, которого я просто не вижу?


person iPwnPancakes    schedule 15.08.2018    source источник
comment
Моей первой попыткой было бы использовать ReactiveVar. Но я еще не пробовал использовать их в withTracker. Вы уже пробовали это? Я думаю, что это должно сработать, так как все реактивные источники данных в withTracker должны вызывать повторный запуск функции.   -  person Christian Fritz    schedule 15.08.2018
comment
Я попытался использовать ReactiveVar, хотя я немного смущен тем, где должен жить ReactiveVar. Поскольку withTracker запускает предоставленную функцию каждый раз, когда что-то изменяется, если я инициализирую ReactiveVar внутри функции withTracker, она повторно инициализируется до своего начального значения (Undefined, null, ' ' и т. д.). Если я передам функциональность ReactiveVar.set компоненту более низкого порядка, тогда он изменится, запустит withTracker, а затем будет повторно инициализирован. По крайней мере, насколько я вижу.   -  person iPwnPancakes    schedule 15.08.2018
comment
Вы должны инициализировать его при загрузке (т. е. непосредственно в файле, где выполняется вызов withTracker, но вне его области действия. Все изменения, которые происходят с ним впоследствии, должны быть теми, которые вы намереваетесь вызвать изменениями.   -  person Christian Fritz    schedule 15.08.2018


Ответы (1)


Как 1#comment90680296_51851675">Кристиан Фриц упомянул в комментарии к моему первоначальному вопросу, я могу использовать ReactiveVar, чтобы иметь возможность передавать входные данные в мой компонент подключения и из него:

export const WritableConnection = function (subscriptionName, collectionAPI) {
    /**
     *  ReactiveVar must be outside of withTracker. If the it was inside withTracker's scope, 
     *  anytime a user would use .set(ANY_VALUE), it would overwrite whatever was in it first,
     *  and then re-initialize.
     **/
    const input = new ReactiveVar(undefined);

    return withTracker(props => {
        const connection = Meteor.subscribe(subscriptionName, input.get());
        const isLoading = connection.ready();

        return {
            ...props,
            isLoading: isLoading,
            collection: collectionAPI.find().fetch(),
            setSearchText: (text) => input.set(text),
            getSearchText: () => input.get()
        }
    })
}
person iPwnPancakes    schedule 16.08.2018