How would I reconfigure a super complicated ternary statement?

Viewed 55

So I'm trying to render an image based on certain boolean values. It works for now with this ternary statement but there's going to be much more options and I was wondering if there's a better way of writing this.

Here is the ternary statement:

<img id="car" alt="" height="200" width="500" src={this.state.isRed && this.state.rimOne ? "/Assets/red.png" : this.state.isRed && this.state.rimTwo ? "/Assets/red2.png" : this.state.isBlue && this.state.rimOne ? "/Assets/Blue.png" : this.state.isBlue && this.state.rimTwo ? "/Assets/Blue2.png" : this.state.isLightBlue && this.state.rimOne ? "/Assets/lightblue.png" : this.state.isLightBlue && this.state.rimTwo ? "/Assets/lightblue2.png" : this.state.isSkyBlue && this.state.rimOne ? "/Assets/Skyblue.png" : this.state.isSkyBlue && this.state.rimTwo ? "/Assets/Skyblue2.png" : this.state.isWhite && this.state.rimOne ? "/Assets/White.png" : this.state.isWhite && this.state.rimTwo ? "/Assets/white2.png" : null}></img>
3 Answers

You could use an if-else statement from your JavaScript to compute the value for src, then use this value in your HTML/view code:

var src = null;
if (this.state.isRed && this.state.rimOne) {
    src = "/Assets/red.png";
}
else if (this.state.isRed && this.state.rimTwo) {
    src = "/Assets/red2.png";
}
else if (this.state.isBlue && this.state.rimOne) {
    src = "/Assets/Blue.png";
}
else if (this.state.isBlue && this.state.rimTwo) {
    src = "/Assets/Blue2.png";
}
else if (this.state.isLightBlue && this.state.rimOne) {
    src = "/Assets/lightblue.png";
}
else if (this.state.isLightBlue && this.state.rimTwo) {
    src = "/Assets/lightblue2.png";
}
else if (this.state.isSkyBlue && this.state.rimOne) {
    src = "/Assets/Skyblue.png";
}
else if (this.state.isSkyBlue && this.state.rimTwo) {
    src = "/Assets/Skyblue2.png";
}
else if (this.state.isWhite && this.state.rimOne) {
    src = "/Assets/White.png";
}
else if (this.state.isWhite && this.state.rimTwo) {
    src = "/Assets/white2.png";
}

It is equivalent to

if (<img id="car" alt="" height="200" width="500" src={this.state.isRed && this.state.rimOne) {
    "/Assets/red.png"
} else {
    if (this.state.isRed && this.state.rimTwo) {
        "/Assets/red2.png"
    } else {
        if (this.state.isBlue && this.state.rimOne) {
            "/Assets/Blue.png"
        } else {
                    if (this.state.isBlue && this.state.rimTwo) {
                "/Assets/Blue2.png"
            } else {
                        if (this.state.isLightBlue && this.state.rimOne) {
                    "/Assets/lightblue.png"
                } else {
                                    if (this.state.isLightBlue && this.state.rimTwo) {
                        "/Assets/lightblue2.png"
                    } else {
                                        if (this.state.isSkyBlue && this.state.rimOne) {
                            "/Assets/Skyblue.png"
                        } else {
                                                    if (this.state.isSkyBlue && this.state.rimTwo) {
                                "/Assets/Skyblue2.png"
                            } else {
                                                        if (this.state.isWhite && this.state.rimOne) {
                                    "/Assets/White.png"
                                } else {
                                                                    if (this.state.isWhite && this.state.rimTwo) {
                                        "/Assets/white2.png"
                                    } else {
                                        null}></img>
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Better to use switch case

I did some codegolfing to come up with this:

function getAssetURL() {
  if (!this.state.rimOne && !this.state.rimTwo)
    return null;
  let s = '/Assets/';
  ['Red', 'Blue', 'LightBlue', 'SkyBlue', 'White'].forEach(c => this.state['is' + c] && (s += c));
  return (s + (this.state.rimTwo ? '2' : '') + '.png').replace(/[RL]|\wB|W.*2/g, l => l.toLowerCase());
}

Here is a demonstration that it produces identical results as another more verbose answer:

'use strict';

const object = {};

['isRed', 'isBlue', 'isLightBlue', 'isSkyBlue', 'isWhite'].forEach(color => {
  ['rimOne', 'rimTwo'].forEach(number => {
    const state = { [color]: true, [number]: true };
    object.state = state;
    console.log(color, number);
    console.log(' ' + getAssetURL1.call(object));
    console.log(' ' + getAssetURL2.call(object));
  });
});

function getAssetURL1() {
  if (!this.state.rimOne && !this.state.rimTwo)
    return null;
  let s = '/Assets/';
  ['Red', 'Blue', 'LightBlue', 'SkyBlue', 'White'].forEach(c => this.state['is' + c] && (s += c));
  return (s + (this.state.rimTwo ? '2' : '') + '.png').replace(/[RL]|\wB|W.*2/g, l => l.toLowerCase());
}

function getAssetURL2() {
  var src = null;
  if (this.state.isRed && this.state.rimOne) {
    src = "/Assets/red.png";
  }
  else if (this.state.isRed && this.state.rimTwo) {
    src = "/Assets/red2.png";
  }
  else if (this.state.isBlue && this.state.rimOne) {
    src = "/Assets/Blue.png";
  }
  else if (this.state.isBlue && this.state.rimTwo) {
    src = "/Assets/Blue2.png";
  }
  else if (this.state.isLightBlue && this.state.rimOne) {
    src = "/Assets/lightblue.png";
  }
  else if (this.state.isLightBlue && this.state.rimTwo) {
    src = "/Assets/lightblue2.png";
  }
  else if (this.state.isSkyBlue && this.state.rimOne) {
    src = "/Assets/Skyblue.png";
  }
  else if (this.state.isSkyBlue && this.state.rimTwo) {
    src = "/Assets/Skyblue2.png";
  }
  else if (this.state.isWhite && this.state.rimOne) {
    src = "/Assets/White.png";
  }
  else if (this.state.isWhite && this.state.rimTwo) {
    src = "/Assets/white2.png";
  }
  return src;
}

Related