Skip to content

Conditional Cases#13

Open
atticoos wants to merge 4 commits intomasterfrom
conditional-cases
Open

Conditional Cases#13
atticoos wants to merge 4 commits intomasterfrom
conditional-cases

Conversation

@atticoos
Copy link
Owner

@atticoos atticoos commented Jun 5, 2017

Seeking Feedback

I'd love to hear from some folks that currently use this, or are interested in using this, in what they think of the approaches behind these two new APIs.

Here we are -- support for multiple cases (#7):

If/ElseIf/Else

<div>
  {renderIf.if(x === 1) (
    <span>Hello, 1</span>
  ).elseIf(x === 2) (
    <span>Hello, 2</span>
  ).elseIf(x === 3) (
    () => <span>Hello, 3</span> // avoid evaluating if unsatisfied
  ).else(
    <span>Hello, {x}</span>
  ).evaluate()}
</div>

Instead of:

<span>
  {renderIf(x === 1) (
    <span>Hello, 1</span>
  )}
  {renderIf(x === 2) (
    <span>Hello, 2</span>
  )}
  {renderIf(x === 3) (
    () => <span>Hello, 3</span> // avoid evaluating if unsatisfied
  )}
  {renderIf(x !== 1 && x !== 2 && x !== 3) (
    <span>Hello, {x}</span>
  )}
</span>

Note: this does not remove renderIf - it's still quite handy and can be used for single conditions

Switch

<div>
  {renderIf.switch(x)
    .case(1) (
      <span>Hello, 1</span>
    )
    .case(2) (
      <span>Hello, 2</span>
    )
    .case(3) (
      () => <span>Hello, 3</span> // avoid evaluating if unsatisfied
    )
    .default(
      <span>Hello, {x}</span>
    )
    .evaluate()
  }
</div>

I'd love if we didn't have to call evaluate() - but I can't imagine it's possible to know when we're at the end of the execution chain.

Tests are still needed for this PR

@atticoos atticoos mentioned this pull request Jun 6, 2017
@stefensuhat
Copy link

stefensuhat commented Jun 7, 2017

will try this package after you merge this. 📦

@rstone770
Copy link

Hey @ajwhite. This looks pretty good to me.

If you want to get rid of evaluate why not just return the evaluate function with the api attached?

renderIf.switch(x)();

renderif.switch(x)
   .case(1)(<span>1</span>)
   .case(2)(<span>2</span>)
   .default(<span>default</span>)();

also i noticed that you are sorting conditions by 'type' before evaluating them, presumably because you'd like to make sure conditions are executed in the proper order. I think it might be better to enforce the behavior you want instead of fixing invalid usages of the library and causing potentially unexpected results. I think the easiest way to do this would be to follow a builder type approach and create a funnel.

Maybe something along these lines.

const multi = () => {
  const cases = [];
  
  function createEvaluator() {
    return function evaluate() {
      for (let index = 0; index < cases.length; index++) {
        if (cases[index].condition) {
          if (typeof cases[index].elemOrThunk === 'function') {
            return cases[index].elemOrThunk(); 
          }

          return cases[index].elemOrThunk;
        }
      }

      return null;
    };
  };
  
  function ifCondition (condition) {
    return (elemOrThunk) => {
      cases.push({ condition, elemOrThunk });
      return ifConditionApi;
    };
  };
  
  function elseCondition (elemOrThunk) {
    cases.push({ condition: true, elemOrThunk });
    return createEvaluator();
  };
  
  const ifConditionApi = Object.assign(
    createEvaluator(),
    {
      else: elseCondition,
      elseIf: ifCondition
    }
  );
 	
  return { if: ifCondition };
};

const renderIf = () => {};
renderIf.if = (condition) => multi().if(condition);

renderIf
  .if(false)('if condition')
  .elseIf(false)('else')
  .elseIf(false)('another else')
  .else('hello')();

renderIf
  .if(false)('if condition')
  .else('hi')();

renderIf
  .if(false)('if condition')
  .else('hi')
  .elseIf(true)('ERROR!!11!!one!')();

@JulianKingman
Copy link

Very handy, I like it! Any plans to merge?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants