reactjsconditional-operatorternary

Ternary operator logic not working for boolean, evaluating to false when it's not false


I'm mapping a little block of project objects for a set of footer links and I want each project name to be followed by a | EXCEPT the last one. Here's the code.

const projects = [
  {
    lastOne: false,
    project: "Kuma",
    link: "",
    image: "./kuma.png",
  },
  {
    lastOne: false,
    project: "Rin Starseed",
    link: "",
    image: "./star.png",
  },
  {
    lastOne: true,
    project: "Sea Harvest",
    link: "",
    image: "./fish.png",
  },
];

Then the logic in the footer component


function ProjectLinks({ link, project, lastOne }) {
  return (
    <a href={link} target="_blank" style={{ color: "white" }}>
      {lastOne ? project + " | " : project}
    </a>
  );
}

It evaluates to false, only lists the project names no |


Solution

  • Your if statement is the wrong way around, it should be:

    {lastOne ? project : (project + " | ")}
    

    You're probably not passing the props to ProjectLinks whereby lastOne is a falsy value and so the | isn't shown.

    You could spread the complete object to pass all the props:

    {projects.map(p => <ProjectLinks {...p} /> )}
    
    Demo:

    const { useState } = React;
    
    const Example = () => {
    
        const projects = [
            {lastOne: false, project: "Kuma", link: "", image: "./kuma.png", },
            {lastOne: false, project: "Rin Starseed", link: "", image: "./star.png", },
            {lastOne: true, project: "Sea Harvest", link: "", image: "./fish.png", },
        ];
    
        return (
            <div>
                {projects.map(p => <ProjectLinks {...p} /> )}
            </div>
        )
    }
    
    function ProjectLinks({ link, project, lastOne }) {
        return (
            <a href={link} target="_blank" style={{ color: "red" }}>
                {lastOne ? project : project + " | "}
            </a>
        );
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>


    But this is not really scalable, since you'll need to loop over the items in the projects array, you can use the iterator of the loop (map() in the examples) to check if that is the last item in the list:

    {projects.map((p, i) => <ProjectLinks {...p} lastOne={i === projects.length - 1} /> )}
    
    Demo:

    const Example = () => {
    
        const projects = [
            { project: "Kuma", link: "", image: "./kuma.png", },
            { project: "Rin Starseed", link: "", image: "./star.png", },
            { project: "Sea Harvest", link: "", image: "./fish.png", },
        ];
    
        return (
            <div>
                {projects.map((p, i) => <ProjectLinks {...p} lastOne={i === projects.length - 1} /> )}
            </div>
        )
    }
    
    function ProjectLinks({ link, project, lastOne }) {
        return (
            <a href={link} target="_blank" style={{ color: "red" }}>
                {lastOne ? project : project + " | "}
            </a>
        );
    }
    ReactDOM.render(<Example />, document.getElementById("react"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>