0

I am attempting to map a large amount of data in React with which Iv'e had a decent amount of success with. Now i'm attempting to retrieve data from a nested JSON object and I have no idea how to. My JSON data is below.

{
    "core-topics": [
        {
            "id": "coding",
            "name": "Coding",
            "headerColour": "blue",
            "description": "Learn how to build your very own website!",
            "image": "https://www.bitdegree.org/tutorials/wp-content/uploads/2018/08/what-is-a-web-developer.jpg",
            "link": [
                {
                    "id": "coding-item-one",
                    "name": "Java"
                },
                {
                    "id": "coding-item-two",
                    "name": "C++"
                },
                {
                    "id": "coding-item-three",
                    "name": "Python"
                }
            ]
        },

I'm accessing this data using a method that searches for a specific component id and then returns the matching data.

const Writer = ({match: {url}, coreTopics}) => {
    return (
        <React.Fragment>
            /* This renders each link from the JSON file */
            /* And maps it onto the card layout component below */
            <Route path = {`${url}/:topicId`} render = {
                /* searches for a matching id and renders all properties if it finds a match */
                ({ match }) => 
                <card {...coreTopics.find(topic => topic.id === match.params.topicId)}/>}/>
        </React.Fragment>
    )
}

While using a template component to render all of the JSON data to a HTML format.

class card extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            links: {}
        }
    }
    render(){
        return(
            <Container>
                <HeaderImage headerImage = {this.props.image}>
                    <ImageTextContainer>
                        <H1> {this.props.name} </H1>
                        <Stripe stripeColour = {this.props.headerColour}/>
                        <P> {this.props.description} </P>
                    </ImageTextContainer>


                    /* What I'm attempting to do with 0 luck. */
                    /* I am also aware the code isn't correct, i'm just demonstrating my logic behind this. */

                    <ul> 
                      {this.props.link.map((name, id)) => 
                          <li id = {link.id}> {link.name} </li>
                       })
                    </ul>
                </HeaderImage>
            </Container>
        )
    }
}

Each time I try to access the properties within the link object, I get an error saying that the map function cannot be used on undefined. It is basically impossible to get any data out of this object and I have no idea why. I can access all of the data easily except any nested objects.

Any help at all is appreciated! I understand this is quite a large post and probably includes too much information but I couldn't think of another way to get this all across to anyone who might be able to help.

1
  • I don't think it's clear for when you are passing your JSON object to the Writer component. For example, you are not looking in core-topics array anywhere in the code you posted.... I would have expected to see yourJsonObject["core-topics"].find(({id}) => id === matchMedia.params.topicId) somewhere. Commented Apr 10, 2020 at 11:54

2 Answers 2

1

In your question, it isn't clear where or how you are passing in the JSON object you listed. But for an example, if I had this object, and wanted to write a function that would return a matching topic... I would write something like this:

const coreTopicsJson = {
  "core-topics": [
      {
          "id": "coding",
          "name": "Coding",
          "headerColour": "blue",
          "description": "Learn how to build your very own website!",
          "image": "https://www.bitdegree.org/tutorials/wp-content/uploads/2018/08/what-is-a-web-developer.jpg",
          "link": [
              {
                  "id": "coding-item-one",
                  "name": "Java"
              },
              {
                  "id": "coding-item-two",
                  "name": "C++"
              },
              {
                  "id": "coding-item-three",
                  "name": "Python"
              }
          ]
      }
  ]
}

const findTopicById = (topicId, coreTopicsJson) => (
  coreTopicsJson["core-topics"].find(({id}) => id === topicId)
)

const codingCoreTopic = findTopicById("coding", coreTopicsJson) // returns object of topic with id of 'coding'

Perhaps this might help on how to pull data from the JSON object?

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer! this unfortunately doesn't seem to do the trick and returns an error saying coreTopicsJson isn't a function.
1

Update the Card component to take data using prop key, do not spread it.

class Card extends React.Component {
  constructor(props){
      super(props);
      this.state = {
          links: {}
      }
  }
  render(){
    const card = this.props.card || {link: []}
      return(
          <Container>
              <HeaderImage headerImage = {card.image}>
                  <ImageTextContainer>
                      <H1> {card.name} </H1>
                      <Stripe stripeColour = {card.headerColour}/>
                      <P> {card.description} </P>
                  </ImageTextContainer>
              </HeaderImage>
          </Container>
      )
  }
}

Pass data using key(prop)

const Writer = ({match: {url}, coreTopics}) => {
  const card = coreTopics.find(topic => topic.id === match.params.topicId)
  return (
      <React.Fragment>
          <Route path = {`${url}/:topicId`} render = {
              ({ match }) => 
              <card card={card}/>}/>
      </React.Fragment>
  )
}

3 Comments

Thanks for the answer! seems to be a viable solution, however I am now getting "match undefined" in the Writer Component when I switch from spreading to your method. Any idea of how to get around this without spreading the props?
Can you elaborate on this please?
can u update question with latest code after modification.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.