Reputation: 277
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
Reputation: 599
You need to handle your subscriptions in withTracker
function 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 withTracker
function. 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