Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client side filtering of collection #147

Open
sungwoncho opened this issue Mar 16, 2016 · 4 comments
Open

Client side filtering of collection #147

sungwoncho opened this issue Mar 16, 2016 · 4 comments

Comments

@sungwoncho
Copy link
Contributor

I would like to know if there is any problem with the way I am implementing the client side search.

I have a component in which users can use search input to filter the documents to be displayed. The component receives an array of documents from a container.

container

export const composer = ({context}, onData) => {
  const {Meteor, Collections} = context();

  if (Meteor.subscribe('foos').ready()) {
    let foos = Collections.Foos.find({some: condition}).fetch();

    onData(null, {foos});
  }
};

To implement the search, I made my component stateful:

class MyComponent extends React.Component {
  ...
  render() {
    <ul>
          {
            foos.filter(foo => {
              let searchRegex = new RegExp(_.escapeRegExp(this.state.searchTerm), 'i');
              return searchRegex.test(foo.name);
            }).map(foo => {
              return <li>{foo.name}</li>;
            })
          }
      </ul>
  }
}

Is filtering the documents a job of the container? I could delegate the job to the container by LocalState but I feel uneasy because LocalState is shared across the whole app, but in this case I don't need my state app-wide.

@tomitrescak
Copy link

@sungwoncho I do this quite often so here is my share of ideas ;)

Yes, this looks like a perfect job for the container. All you need to do is to pass down to component a callback function like "onSearch(searchString)" that will execute back on the container, filtering your data and re-rendering your component. I am not sure I am explaining myself, please let me know.

@tomitrescak
Copy link

Just to give better example here here is the code for filtering container which I use very often:

// this function is part of your component actions
export default {
  ...
  filter(data, string) {
     if (!string) return data;

     // perform filtering of data
     return data.filter(...); 
  }
}

// this is your container
// this looks a bit cut throat but isolates the need for using local state and maintains everything inside the module

export const composer = ({context, filter}, onData) => {
  const {Meteor, Collections} = context();

  if (Meteor.subscribe('foos').ready()) {
    let foos = Collections.Foos.find({some: condition}).fetch();

    function getData(searchText)  {
      return {
        foos: filter(context, foos, searchText),
        onSearch(text) { 
           onData(null, getData(text)); // this will filter data and re-draw the component
        } 
      }
    }

    onData(null, getData());
  }
};

export const depsMapper = (context, actions) => ({
  filter: actions.mycomponent.filter,
  context: () => context
});

This way your component stays nice and stateless having several easy to test methods.

@norain2050
Copy link

norain2050 commented Nov 24, 2016

@tomitrescak I`m sorry,i dont understand the code,below:

  onSearch(text) { 
           onData(null, getData(text)); // this will filter data and re-draw the component
        } 

Can the onData function be used directly by the component ?

@achtan
Copy link
Contributor

achtan commented Nov 24, 2016

use onSearch in your component as an event handler for search action.

<input onChange={onSearch}/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants