Hi out there,
I am a bit struggling with a “Blaze” simple question but get lost when trying to solve this using React, Flow-Router, React-Komposer.
I have 3 Elements:
- MainLayout
- SearchEntry (InputBox)
- ItemsList
The app will subscribe to the complete collection “items” on start to sync all data to the client. Then I just want to filter the items list whenever something is entered in the SearchEntry
To save the current searchBy
state I may either use a ReactiveVar or a Component State.
stateVar_searchBy = new ReactiveVar("");
My FlowRoute looks like:
FlowRouter.route("/", {
action(params) {
mount(Layout, {
header: <searchEntry />,
content: <ItemsList searchBy={stateVar_searchBy.get()} />
});
}
});
I mount data using react-komposer
function composer(props, onData) {
const handle = Meteor.subscribe("items");
if (handle.ready()) {
const items = Items.find(props.searchBy == "" ? {} : { title: new RegExp(props.searchBy, 'i') }).fetch();
onData(null, {items});
};
};
export default composeWithTracker(composer)(ItemsList);
My Problem is now, that the composer function is not reactive
, so whenever I change the value of my ReactiveVar stateVar_searchBy
the List won’t get re-rendered.
Q: My question is now how I may change the props value of the ItemsList to get a new filtered list based on the search input.
Thanks for some help on this
Tom
I do something like the following for bowling center application…
I use a global ‘theApp’ for storing the filter (and everything else the app uses).
Here is my container … the filter is reactive and is being updated by the component
import theApp from '/imports/startup/client/theApp.js'
import { composeWithTracker } from 'react-komposer';
import { Bowlers } from '/imports/api/collections';
import { SelectBowlerAll } from '../components/select-bowler-all.js';
import { Loading } from '../components/loading.js';
const composer = (props, onReady) => {
const filter = theApp.selectAllFilter.get();
const handleData = theApp.theSubsManager.subscribe('leagueBowlersAll', filter);
if (handleData.ready()) {
const data = Bowlers.find({ name: new RegExp(filter,'i')}).fetch();
onReady(null, { data, filter });
}
};
export default composeWithTracker(composer, Loading)(SelectBowlerAll);
the component looks like this … where the filter gets updated
const handleChange = (filter, event) => {
theApp.selectAllFilter.set(event.target.value);
}
export const SelectBowlerAll = ({ data, filter }) => {
...
return (
<div className="text-center">
<h3>Select a Bowler</h3>
<input autoFocus type="text" placeholder ='Bowler name...' value={filter} onChange={handleChange.bind(this, filter) } />
</div>
);
Hi Paul ( @stocksp )
thanks for posting. So you don’t use a components prop but some global reactive data for your filter.
I really would like to know how to do this via a component prop so that the component may function without some global knowledge.
Maybe someone could guide us about “the react way”?
All the react examples I’ve seen use a global store (like Redux) for holding on to the ‘filter’ … my ‘store’ is ‘theApp’.
I am not sure if even that all seen so far are doing via globals is the correct and really preferred solution for that.
@arunoda maybe you may chip in and give us some short guidiance (maybe also how to do it mantra style)
Thanks all for comments
Tom
I updated the title for better understanding and in hope to get some more response.
Thanks for help in advance.
Tom
1 Like