Search code examples
javascriptif-statementreact-nativees6-promise

Writing if/else statements with 3 conditions with a promise mixed in


So I have this conditional statement with 2 conditions, whereby

let modItemList = this.props.items

    if (this.state.searchItemName) {   // condition1
        modItemList = (
            this.props.items.filter(
                (item) => item.name.toLowerCase().indexOf(lcName) !== -1    // For name
            )
        );
    } else if (this.state.searchItemAddress) {    //condition2
        modItemList = (
            this.props.items.filter(
                (item) => item.fullAddress.some(e => e.toLowerCase().indexOf(lcAddress) !== -1)      // For Address
            )
        );
    } 

This is where it's a little tricky to explain.

Now I want to add a 3rd condition, which happens only if both condition1 and condition2 are met, AND the outcome is that of executing code from condition1 and condition2.

How would I go about expressing that?


Solution

  • There's no asynchronous action here, so no need to track an async action with a promise.

    Probably the simplest thing is to filter the filtered list:

    let modItemList = this.props.items;
    if (this.state.searchItemName) {
        modItemList = modItemList.filter(item => item.name.toLowerCase().includes(lcName));
    }
    if (this.state.searchItemAddress) {
        modItemList = modItemList.filter(item => item.fullAddress.some(e => e.toLowerCase().includes(lcAddress)));
    }
    

    Or filter once and check for searchItemName and searchItemAddress within the callback:

    let modItemList = this.props.items.filter(item =>
        (!this.state.searchItemName    || item.name.toLowerCase().includes(lcName)) &&
        (!this.state.searchItemAddress || item.fullAddress.some(e => e.toLowerCase().includes(lcAddress));
    

    Even if the list is in the hundreds of thousands of entries, neither of those is going to be slow enough to worry about.

    Or if it really bothers you do do that double-filtering or re-checking, build a filter function:

    let modItemList;
    let filterFunc = null;
    if (this.state.searchItemName && this.state.searchItemAddress) {
        filterFunc = item => item.name.toLowerCase().includes(lcName) && item.fullAddress.some(e => e.toLowerCase().includes(lcAddress));
    } else if (this.state.searchItemName) {
        filterFunc = item => item.name.toLowerCase().includes(lcName);
    } else if (this.state.searchItemAddress) {
        filterFunc = item => item.fullAddress.some(e => e.toLowerCase().includes(lcAddress));
    }
    modItemList = filterFunc ? this.props.items.filter(filterFunc) : this.props.items;
    

    That involves repeating yourself a bit, though, leaving open the possibility that you'll update one address filter but not the other. You can aggregate the filter functions:

    let nameCheck    = item => item.name.toLowerCase().includes(lcName);
    let addressCheck = item => item.fullAddress.some(e => e.toLowerCase().includes(lcAddress));
    let modItemList;
    if (this.state.searchItemName && this.state.searchItemAddress) {
        modItemList = this.props.items.filter(item => nameCheck(item) && addressCheck(item));
    } else if (this.state.searchItemName) {
        modItemList = this.props.items.filter(nameCheck);
    } else if (this.state.searchItemAddress) {
        modItemList = this.props.items.filter(addressCheck(item);
    }
    

    If there were more than two, we might look at putting them in an array and doing

    modItemList = this.props.items.filter(item => arrayOfFunctions.every(f => f(item)));
    

    So...lots of options. :-)


    I've used includes(x) rather than indexOf(x) !== -1 above. I find it clearer.