Home > Software design >  How to use conditional rendering inside map in React
How to use conditional rendering inside map in React

Time:10-31

I have a react page that is rendering a list of products that are being returned from a GraphQL API. Once the products are returned, I'm storing them in a state and then render them. How do I only render products that meet certain conditions?

Right now, I'm mapping over the products and rendering each one. This is working correctly. But if I try to use conditional statements, I get errors in my IDE. This is the code I currently have. This is currently working:

async function contactAPI() {
  return await axios({
    url: 'https://graphqlexample.com/api/products',
    method: 'post',
    data: {
      query: `
      QUERY GOES HERE
        `
    }
  })
}

function App() {  
  const [products, setProducts] = useState([]);

  useEffect(() => {
    async function getData() {
      const res = await contactAPI();
      setProducts(res.data.data.products);
    }
    getData();
  }, []);

  return (
    <div>
        <div>          
          {products.map(p =>           
          (             
          <div>            
            <ProductCard productName={p.productName} />
          </div>
          ))}
        </div>    
    </div>
  );
} 

I need to check p.productName to see if it meet certain conditions, and if it does, render it. If not, don't render. I tried using different conditionals inside of map, but keep getting errors.

CodePudding user response:

As an example you can just return the JSX if it will meet certain criterion as:

Note: For demo purpose I've used includes method. You can specify the condition

(<div><ProductCard productName={p.productName} /></div>)

and will only render if the first condition is true

  <div>
    {products.map((p) => (
      p.productName.includes("free") && (<div><ProductCard productName={p.productName} /></div>)
    ))}
  </div>

Codesandbox Demo

export default function App() {
  const arr = [1, 2, 3, 4, 5];
  return (
    <div>
      {arr.map((n) => {
        return n % 2 === 0 && <div key={n}>{n}</div>;
      })}
    </div>
  );
}

CodePudding user response:

map will always return an array of the same length so you'll be returning some empty elements depending on the condition which isn't optimal.

Instead filter the data first, and then map over the returned array. That way you're only mapping over the data you need to display.

const { useState } = React;

function App({ data }) {

  const [ products, setProducts ] = useState(data);

  // In this example we take the list of products in
  // state and return a new array of only those products
  // that aren't soap. We then `map` over that array in our
  // component render
  function getFilteredProducts() {
    return products.filter(product => {
      const name = product.productName.toLowerCase();
      return !name.includes('soap');
    });
  }

  // Get an array of filtered products and then `map` over it
  // to produce the product cards
  return (
    <div>
      {getFilteredProducts().map(product => {
        return (
          <ProductCard
            key={product.id}
            id={product.id}
            name={product.productName}
          />
        );
      })}
    </div>
  );
};

function ProductCard({ id, name}) {
  return <div>{id}: {name}</div>;
}

const data=[{id:1,productName:"Blue Soap"},{id:2,productName:"Beans"},{id:3,productName:"Green Soap"},{id:4,productName:"Sponge"},{id:5,productName:"Chicken"}];

ReactDOM.render(
  <App data={data} />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

{
    products.map(id => {
      return condition == true ?
        <div>            
          <ProductCard productName={p.productName} />
        </div>
    : <div></div>
})}

CodePudding user response:

const products = [
  { productName: "product1" },
  { productName: "product2" },
  { productName: "product3" }
];

const App = () => {
  return (
    <div className="App">
      <div>
        {products.map((p, index) => {
          if (p.productName === "product1") {
            return <div key={index}>{p.productName}</div>;
          }
          return <React.Fragment></React.Fragment>;
        })}
      </div>
    </div>
  );
}

ReactDOM.render(
    <App />,
    document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related