最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ternary operator in map() react - Stack Overflow

programmeradmin2浏览0评论

I made an application in React that shows state holidays using state codes. Now I'm wondering how to handle error when a user types in a non-existent state code or more characters. Here's my try to do it.

import React from "react";

const Holidays = props => {
if (props.dataLoaded === false) {
    return null;
  } else {
return (
  <div className="table-responsive">
    <table>
      <thead>
        <tr>
          <th>Holiday</th>
          <th>Date</th>
          <th>Type</th>
        </tr>
      </thead>
      <tbody>
        {props.country.map((country, index) =>
          country && index === undefined ? (
            <p>{props.error}</p>
          ) : (
            <React.Fragment key={index}>
              <tr>
                <td className="holiday-name">
                  <strong>{country.name}</strong>
                  <br />
                  <p>{country.description}</p>
                </td>
                <td className="holiday-date">
                  {country.date.datetime.day}.{country.date.datetime.month}.
                  {country.date.datetime.year}
                </td>
                <td className="holiday-type">
                  {country.type[0]} {country.type[1]}
                </td>
              </tr>
            </React.Fragment>
        )
          )}
          </tbody>
         </table>
       </div>
      );
    }
      };

 export default Holidays;

But with this code when a non-existing state code or more characters is typed in, it throws a error "TypeError: Cannot read property 'map' of undefined".Any help is acceptable

I made an application in React that shows state holidays using state codes. Now I'm wondering how to handle error when a user types in a non-existent state code or more characters. Here's my try to do it.

import React from "react";

const Holidays = props => {
if (props.dataLoaded === false) {
    return null;
  } else {
return (
  <div className="table-responsive">
    <table>
      <thead>
        <tr>
          <th>Holiday</th>
          <th>Date</th>
          <th>Type</th>
        </tr>
      </thead>
      <tbody>
        {props.country.map((country, index) =>
          country && index === undefined ? (
            <p>{props.error}</p>
          ) : (
            <React.Fragment key={index}>
              <tr>
                <td className="holiday-name">
                  <strong>{country.name}</strong>
                  <br />
                  <p>{country.description}</p>
                </td>
                <td className="holiday-date">
                  {country.date.datetime.day}.{country.date.datetime.month}.
                  {country.date.datetime.year}
                </td>
                <td className="holiday-type">
                  {country.type[0]} {country.type[1]}
                </td>
              </tr>
            </React.Fragment>
        )
          )}
          </tbody>
         </table>
       </div>
      );
    }
      };

 export default Holidays;

But with this code when a non-existing state code or more characters is typed in, it throws a error "TypeError: Cannot read property 'map' of undefined".Any help is acceptable

Share Improve this question asked Feb 25, 2019 at 18:06 branen890branen890 411 gold badge1 silver badge5 bronze badges 6
  • 1 The error means that props.country is undefined – Pointy Commented Feb 25, 2019 at 18:06
  • if (props.dataLoaded === false) is fairly non-idiomatic, and possibly the problem (if your props doesn't have dataLoaded at all in the case of the data not [yet?] being loaded). The idiomatic check would be if (!props.dataLoaded). – T.J. Crowder Commented Feb 25, 2019 at 18:08
  • Here is in a codepen codepen.io/branen890/pen/MxWyXv – branen890 Commented Feb 25, 2019 at 18:09
  • The problem is almost certainly in the use of Holiday, which you haven't shown. Apparently there is no country prop being passed. (And if it's an array, it really should be called countries.) – T.J. Crowder Commented Feb 25, 2019 at 18:10
  • 2 @branen890 - Please don't hide part of the code off-site. Make sure all the necessary code is here, on-site, because A) People shouldn't have to go off-site to help you, and B) Links rot. Please use Stack Snippets (the [<>] toolbar button) to provide your runnable example. Stack Snippets support React, including JSX; here's how to do one. – T.J. Crowder Commented Feb 25, 2019 at 18:11
 |  Show 1 more ment

2 Answers 2

Reset to default 5

The issue with your code is that your data props.country is being mapped before the data is defined, and as we know the map method .map() can only be used on arrays. Check here for more details. Therefore when you try use map on something that is undefined it will throw that error.

The reason that it is undefined at first is in most scenarios because you are fetching the data from the backend either from a server or from some public API. Before the operation of the data that is being fetched is plete your props.country will be undefined or whatever you initialize it to.

What you should do is change your current code of:

{props.country.map((country, index) =>
          country && index === undefined ? (
            <p>{props.error}</p>
          ) : (
            <React.Fragment key={index}>
              <tr>
                <td className="holiday-name">
                  <strong>{country.name}</strong>
                  <br />
                  <p>{country.description}</p>
                </td>
                <td className="holiday-date">
                  {country.date.datetime.day}.{country.date.datetime.month}.
                  {country.date.datetime.year}
                </td>
                <td className="holiday-type">
                  {country.type[0]} {country.type[1]}
                </td>
              </tr>
            </React.Fragment>
        )
)}

To something like below, where we make a check of your props.country and make sure that it's loaded - once it is, then try use map on it to render out the contents.

{props.country ? props.country.map((country, index) =>
          country && index === undefined ? (
            <p>{props.error}</p>
          ) : (
            <React.Fragment key={index}>
              <tr>
                <td className="holiday-name">
                  <strong>{country.name}</strong>
                  <br />
                  <p>{country.description}</p>
                </td>
                <td className="holiday-date">
                  {country.date.datetime.day}.{country.date.datetime.month}.
                  {country.date.datetime.year}
                </td>
                <td className="holiday-type">
                  {country.type[0]} {country.type[1]}
                </td>
              </tr>
            </React.Fragment>
        )
): <div>Data Loading!</div>}

So what we are doing here is adding another ternary conditional statement to check if props.country is true THEN apply the map method, else you simply return the div with contents "Data Loading!" before the data is loaded.

To clarify we are adding props.country ? right at the start of your code inside the opening curly brace { and : <div>Data Loading!</div> at the end right after the last closing bracket ) and before the closing curly brace }.

Now this <div>Data Loading!</div> could be anything you don't have to put a div or text you could simply put null, but before the data is fetched in those split seconds there will be empty space where your output would be.

Experiment with what you want to put there, but something nice would be to put a loader like a spinner or a styled message to indicate that your data is being fetched.

Edit: You could also initialize your props.country to an array, so that using .map on it does not resolve into an error automatically even when it's empty. If this was passed down as a props from your parent ponent's state, simply do:

state = {
   country: []
}

The prior methods to solving this problem are better, though. But you should still probably get used to initializing your state properties with the data that they will eventually hold.

import React from "react";

const Holidays = props => {
  return (
    <div className="table-responsive">
      <table>
        <thead>
          <tr>
            <th>Holiday</th>
            <th>Date</th>
            <th>Type</th>
          </tr>
        </thead>
      <tbody>
        {!props.country || props.country.length == 0 ? <p>{props.error}</p> : props.country.map((country, index) =>
            <React.Fragment key={index}>
              <tr>
                <td className="holiday-name">
                  <strong>{country.name}</strong>
                  <br />
                  <p>{country.description}</p>
                </td>
                <td className="holiday-date">
                  {country.date.datetime.day}.{country.date.datetime.month}.
                  {country.date.datetime.year}
                </td>
                <td className="holiday-type">
                  {country.type[0]} {country.type[1]}
                </td>
              </tr>
            </React.Fragment>
          )}
        </tbody>
      </table>
    </div>
  );
};

export default Holidays;
发布评论

评论列表(0)

  1. 暂无评论