Mapping an array present inside an object working only when given in conditional statement

Viewed 79

I am using Reactjs.

I wanted to render an array present inside an object.

state = {
   obj: { 
           name: abhishek,
           age: 23,
           characterList: ['a','b','c','d']
        }
}

I found out that in order to render the characterList I had to wrap it in a conditional statement.

And I'm not able to figure out the reason.

Incorrect:

render(){
return(
         <>
             {
                 this.state.obj.characterList.map((character, i) => {
                      return(
                          <h1>{character}</h1>
                      )
                 })
             }
         </>
      )

This gives error - 'cannot read property 'map' of undefined'

But if given in conditional statement like this -

Correct:

render(){
return(
         <>
             { this.state.obj.characterList ? 
               (
                   this.state.obj.characterList.map((character, i) => {
                        return(
                            <h1>{character}</h1>
                        )
                   })
               ) : null
             }
         </>
      )

Original Code: which is giving error (cannot read property 'map' of undefined)

export default (props) => {
  const [FAQs, setFAQs] = useState([]);

  useEffect(async () => {
    const res = await Axios.get("http://localhost:5000/FAQs/getFAQs");
    setFAQs(res.data);
    console.log(res.data);
  }, []);

  return (
    <React.Fragment>
      <div className="faqs-wapper">
        <div className="faqs-heading">
          <h1>Frequently asked questions</h1>
          <h2>{FAQs.category}</h2> //This works fine.
        </div>
        { 
            FAQs.FAQList.map((QA,i) => {
                return (
                    <div key={i}>
                        <p>{QA.question}</p>
                    </div>
                )
            })
        }
      </div>
    </React.Fragment>
  );
};

res.data coming is:

{
   category: "Getting Started",
   FAQList: [
                {
                   question: "is two factor authentication mandatory?",
                   answer: "Clients are required to perform 2FA."
                },
                {
                   question: "how long does transfer take?",
                   answer: "Depends on amount."
                },
            ]
}

Original Code: which is working when given in conditional statement

export default (props) => {
  const [FAQs, setFAQs] = useState([]);

  useEffect(async () => {
    const res = await Axios.get("http://localhost:5000/FAQs/getFAQs");
    setFAQs(res.data[0]);
    console.log(res.data[0]);
  }, []);

  return (
    <React.Fragment>
      <div className="faqs-wapper">
        <div className="faqs-heading">
          <h1>Frequently asked questions</h1>
          <h2>{FAQs.category}</h2> //This works fine.
        </div>
        { FAQs.FAQList ?
            FAQs.FAQList.map((QA,i) => {
                return (
                    <div key={i}>
                        <p>{QA.question}</p>
                    </div>
                )
            }) : null
        }
      </div>
    </React.Fragment>
  );
};
1 Answers

You are initializing FAQs to be an empty array in your useState. After your api request is complete your setFAQs method appears to set FAQs as an object with FAQList as a key on the FAQs object. Change setFAQs(res.data) to setFAQs(res.data.FAQList) and change your map to FAQs.map from FAQs.FAQList.map

Your original error is happening because the component is rendered before the api request is complete and FAQs.FAQList is undefined. You are trying to look up a property on an undefined value here: FAQs.FAQList.map which throws a type error.

Related