1

My data is following

  data=[
{
id: 1,
name: 'John Doe',
contacts: '[email protected]',
accepted: true
},
{
id: 2,
name: 'Jane Doe',
contacts: '[email protected]',
accepted: false
},

]

I want to filter (if filterKey variable is not empty/null) and sort(if sortKey variable is not empty/null). I can do it with some if/then but is there a better way?

 let computedList = data
 if(filterKey) {
      computedList = data.filter(item => item.name.includes(filterKey))
 }  
 if(sortKey) {
      computedList = data.sort(...)
 }
 computedList.map(item => <div>item.name</div>)
3
  • Where do filterKey and sortKey come from? Commented Oct 25, 2017 at 13:10
  • Your solution doesn't work if both filterKey and sortKey are present, it always sorts the data not the result of the filter. Commented Oct 25, 2017 at 13:11
  • Yes, you are right. I meant to use computedList in sortKey block. filterKey and sortKey come externally (from React props). Commented Oct 25, 2017 at 13:21

2 Answers 2

2

I can do it with some if/then but is there a better way?

Not really, no. That's the cleanest, clearest way, there's really no need for an alternative unless you're working in certain programming styles (like functional programming), which you don't appear to be. But you want to use computedList, not data, in the sort statement (in case you've filtered). And of course you need to do something with the return value of map.


Side note: sort is in-place, so no need for the assignment, and if you aren't the owner of the array data points to, you may want to clone first if you aren't filtering. E.g.:

let computedList = filterKey ? data.filter(item => item.name.includes(filterKey)) : data.slice();
if (sortKey) {
    computedList.sort(/*...*/);
}
let result = computedList.map(item => <div>item.name</div>);

or perhaps

let computedList = data;
if (filterKey) {
    computedList = computedList.filter(item => item.name.includes(filterKey));
}
if (sortKey) {
    if (!filterKey) {
        computedList = computedList.slice();
    }
    computedList.sort(/*...*/);
}
let result = computedList.map(item => <div>item.name</div>);

...to avoid making the copy unless you need to.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I meant to use computedList in sortKey block
@Alexandru-IonutMihai: Reading your deleted answer, though, I can see several issues if that's helpful: It always makes copies of the array, even if it doesn't need to; it calls String#includes repeatedly with undefined/""/null in the case where filterKey is falsy; it calls sort when there's no need to sort, and falsely claims all the entries are equal in that case (which breaks the sort callback contract). So ... :-)
1

Nothing is wrong with an if/else now and then. However, you can "hide" the ifs using functions' composition:

const data = [ 
  {id: 1, name: 'John Doe', contacts: '[email protected]', accepted: true},
  {id: 2, name: 'Jane Doe', contacts: '[email protected]', accepted: false},
  {id: 3, name: 'Jane J', contacts: '[email protected]', accepted: false}
];

const filter = (data, filterKey) => filterKey ? data.filter(item => item.name.includes(filterKey)) : data

const sort = (data, sortKey) => sortKey ? [...data].sort((a, b) => a[sortKey] > b[sortKey]) : data

const filterKey = 'Doe'
const sortKey = 'name'
const computedList = sort(filter(data, filterKey), sortKey)
      // .map(item => <div>item.name</div>) // removed for the demo
console.log(computedList);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.