Art
Art

Reputation: 277

Meteor React - can re-subscribe to another subscription on button click

I subscribe to data at the beginning using withTracker

export default withTracker(({ params }) => {
    const dataHandle = Meteor.subscribe('publishData');
    const loadingData = !dataHandle.ready();

    return {
        loadingData,
        dataHandle,
        data: Data.find({}).fetch(),
    }    
})(ShowData);

What I'm trying to achieve is to be able to re-subscribe to a different Publication on a button click. I pass an object of parameters that filters the data.

So I have a button that has onClick={this.applyFilters.bind(this, filters)}

applyFilters(filters) {

    this.props.dataHandle = Meteor.subscribe('publishFilteredData', filters);

}

but nothing happens. It doesn't re-subscribe to anything. When I do dataHandle.stop() before new subscription, it subscribes back to publishData that initialized at the beginning.

Upvotes: 0

Views: 258

Answers (1)

Gokhan Karadag
Gokhan Karadag

Reputation: 599

You need to handle your subscriptions in withTrackerfunction based on your condition applyFilters. However, the point here is that you need to keep that condition in a state and access it in the withTrackerfunction. In this Meteor Forum thread this issue is discussed. Although it is possible to set/get React state within withTracker the better practice is to split the component into two, one of which holds the state and handles events and the other (stateless one) is for displaying results, only and to be fed to the withTracker function. You can also refer to the this Stackoverflow question. So your code would be more or less like the one at the below.

On the other hand, when changing between subscriptions, there is a brief period where both subscriptions are loaded in Meteor. You can find more info about it here. So, if your aim is only to filter data visually rather than some privacy needs etc., I recommend subscribing to all data available to user and filter the data via client side queries on Minimongo.

export default class ShowData extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            applyFilters: false,
        };
    }
    handleApplyFilters= () => {
        this.setState({
            applyFilters: !this.state.applyFilters,
        });
    };

    render () {
        return (
            <Container
                applyFilters={this.state.applyFilters}
                handleApplyFilters={this.handleApplyFilters}
            />
        );
    }
}

// Child component, renders only
const StatelessComponent = ({ handleApplyFilters }) => {
   return(
     <div>
      // Display your data
        <button onClick={handleApplyFilters}>Filter</button>
     </div>
   );

};

// Do all your reactive data access in this method.
// Note that this subscription will get cleaned up
// When your component is unmounted
const Container = withTracker((props) => {
    const filters = ''; // define your filters here
    let dataHandle; 
    if (props.applyFilter) {
      dataHandle = Meteor.subscribe('publishFilteredData', filters);
    } else {
      dataHandle = Meteor.subscribe('publishData');
    }
    const loadingData = !dataHandle.ready();
    return {
        loadingData,
        dataHandle,
        data: Data.find({}).fetch(),
    }    
})(StatelessComponent);

Upvotes: 2

Related Questions