skip to Main Content

After making an api request and getting the data in searchbar.js component, I passed the data to another component (ShowList.js). But I was not able to map over the data.

Searchbar.js
import React from 'react'
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import ShowsList from './ShowsList'
import { useState } from 'react'
import axios from 'axios';

const Searchbar = () => {
  const [searchText, setSearchText] = useState('');
  const [showData, setShowData] = useState([]);
  async function handleSearch(e) {
    e.preventDefault()
    const config = { params: { q: searchText } };
    const response = await axios.get(`https://api.tvmaze.com/search/shows?q=`, config);
    setShowData(response.data);
    showData.map(singleShow => {
      console.log(singleShow)
    })
  }

  return (
    <div>
      <Form>
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Tv Show: </Form.Label>
          <Form.Control type="text" placeholder="Search TV show" onChange={(e) => setSearchText(e.target.value)} />

        </Form.Group>


        <Button variant="primary" onClick={handleSearch}>
          Search
        </Button>
      </Form>
      <ShowsList showData={showData} />
    </div>
  )
}

export default Searchbar

Output for Searchbar.js component

ShowList.js
import React from 'react'

const ShowsList = ({showData}) => {
  showData.map(singleShow => {
    console.log(singleShow)
  })
  return (
    <>ShowList</>
    )
}

export default ShowsList

Output after mapping over the same data array in ShowList.js component

ShowList.js

There is no problem in accessing the data without mapping.

import React from 'react'

const ShowsList = ({showData}) => {
    console.log(showData)
  return (
    <>ShowList</>
    )
}

export default ShowsList

Data accessing without mapping

2

Answers


  1. React does not work like that, if you make a console.log(showData) right after the setShowData(response.data); you will see the value remains the same, this is because the state is actually set after you leave the current function where you call the setState, if you think about it, it has a lot of sent.

    The way you can achieve this is either maping the response.data directly or using useEffect hook for this particular state, something like this:

    import React from 'react'
    import Button from 'react-bootstrap/Button';
    import Form from 'react-bootstrap/Form';
    import ShowsList from './ShowsList'
    import { useState, useEffect } from 'react'
    import axios from 'axios';
    
    const Searchbar = () => {
      const [searchText, setSearchText] = useState('');
      const [showData, setShowData] = useState([]);
      async function handleSearch(e) {
        e.preventDefault()
        const config = { params: { q: searchText } };
        const response = await axios.get(`https://api.tvmaze.com/search/shows?q=`, config);
        setShowData(response.data);
      }
    //triggered after set and rendered showData
    useEffect(() => {
            showData.map(singleShow => {
              console.log(singleShow)
            })
        },[showData])
      return (
        <div>
          <Form>
            <Form.Group className="mb-3" controlId="formBasicEmail">
              <Form.Label>Tv Show: </Form.Label>
              <Form.Control type="text" placeholder="Search TV show" onChange={(e) => setSearchText(e.target.value)} />
    
            </Form.Group>
    
    
            <Button variant="primary" onClick={handleSearch}>
              Search
            </Button>
          </Form>
          <ShowsList showData={showData} />
        </div>
      )
    }
    
    export default Searchbar
        
    
    Login or Signup to reply.
  2. the error shows that you are trying to invoke a map function on an undefined value, you can try to set a default value to the showData props to make sure it is an array if it is undefined

    import React from 'react'
    
    const ShowsList = ({ showData = [] }) => {
      showData.map(singleShow => {
        console.log(singleShow)
      })
      return (
        <>ShowList</>
        )
    }
    
    export default ShowsList
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search