0

let's say i wanted refactor this approach, rather than using a for loop, is there any other way to do this dynamically

  //to apply filter functions in one loop
  const booleanFilterFunctions = [
    (launchData) =>
      launchData.launch_year === filterState.year ||
      filterState.year === "0000",
    (launchData) => launchData.launch_success === filterState.launch,
    (launchData) => launchData.land_success === filterState.landing,
  ];
return (
 <div className={styles.grid}>
          {data
            .filter((launchData) => {
              let result = true;
              for (let i of booleanFilterFunctions)
                result = result && i(launchData);
              return result;
            })
            .map((launchData) => (
              <a key={launchData.flight_id} className={styles.card}>
                <img alt={launchData.links.mission_patch_small} loading="lazy" src={launchData.links.mission_patch_small}></img>

                <h3>
                  {launchData.mission_name} #{launchData.flight_number}
                </h3>
              </a>
            ))}
        </div>);
3
  • I think you want Code Review: codereview.stackexchange.com Commented Sep 26, 2020 at 15:46
  • hmm maybe but kind of a blurred line between review and asking for a better approach, this certainly isn't for work :p Commented Sep 26, 2020 at 17:17
  • You might want to check out composing predicates using And = (f, g) => x => f(x) && g(x) and Or = (f, g) => x => f(x) || g(x) like I describe in this answer Commented Sep 29, 2020 at 8:20

2 Answers 2

1

You can use the array every method for this:

data.filter(launchData =>
  booleanFilterFunctions.every(i => i(launchData))
)
Sign up to request clarification or add additional context in comments.

2 Comments

i'm looking for a composition kind of way, every would take only 1 function, maybe i shoul have been more clear, what i want to do is getList of available functions let's say from a user, apply them all in one go
@IshankSharma No, the every in my answer is called on that list of available functions (booleanFilterFunctions) and runs them all (i(launchData)). It does exactly the same thing as the loop in your question.
0

Instead of applying 3 filter functions one after the another, have you considered chaining the internal boolean logic? From the logic it looks like you want to show the content only when the 3 conditions are fulfilled. You can do something like this..

const filterData = (launchData) =>
  (launchData.launch_year === filterState.year ||
    filterState.year === "0000") &&
  launchData.launch_success === filterState.launch &&
  launchData.land_success === filterState.landing;


return (
 <div className={styles.grid}>
          {data
            .filter(filterData)
            .map((launchData) => (
              <a key={launchData.flight_id} className={styles.card}>
                <img alt={launchData.links.mission_patch_small} loading="lazy" src={launchData.links.mission_patch_small}></img>

                <h3>
                  {launchData.mission_name} #{launchData.flight_number}
                </h3>
              </a>
            ))}
        </div>);

You should be able to go even further on optimization and can avoid the extra iteration through data, by putting the condition directly on the content. Something like,

const shouldShowContent = (launchData) =>
  (launchData.launch_year === filterState.year ||
    filterState.year === "0000") &&
  launchData.launch_success === filterState.launch &&
  launchData.land_success === filterState.landing;


return (
 <div className={styles.grid}>
          {data
            .map((launchData) => shouldShowContent(launchData) && (
              <a key={launchData.flight_id} className={styles.card}>
                <img alt={launchData.links.mission_patch_small} loading="lazy" src={launchData.links.mission_patch_small}></img>

                <h3>
                  {launchData.mission_name} #{launchData.flight_number}
                </h3>
              </a>
            ))}
        </div>);

5 Comments

yes i have but that would default the purpose of question, to allow more dynamic behaviour
No, you should not "put the condition directly on the content". That will render an array of false values.
@Bergi right. But react doesn't render "false" value. That means it'll only render non-falsy elements. Let me know if I'm missing anything here.
Yes, react might filter them out for you, but it's still not a good practice to mix different types in the same array. The .filter(shouldShowContent) call is much cleaner (and there's hardly potential for micro-optimisation). At least use something like shouldShowContent(launchData) ? <a>…</a> : null if you think it's necessary.
Hmm.. right that makes sense to not have react render different types from the same array. Thanks!

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.