I have a Json file to be fetched. I fetched the data and can get the data in the console from App.js. But when I pass the data as props to my child component, it gives me an empty array and does not display the items. What could be the mistake here ? My json data and components are below
App.js import React, { useEffect, useState } from "react"; import logo from "./logo.svg"; import "./App.css"; import ProcessContainer from "./components/AdoptionProcess/ProcessContainer"; function App() { const [adoptionProcess, setAdoptionProcess] = useState([]) async function fetchAsync () { let response = await fetch('./data.json'); let data = await response.json(); return data; } fetchAsync() .then(data => setAdoptionProcess(data)) useEffect(() => { fetchAsync() },[]) return ( <div className="App"> <ProcessContainer adoptionProcess={adoptionProcess}/> </div> ); } export default App;
ProcessContainer.js import React, { useEffect, useState } from "react"; import ProcessItems from "./ProcessItems"; import { Container, Row, Col } from "react-bootstrap"; import 'bootstrap/dist/css/bootstrap.min.css'; const ProcessContainer = ({adoptionProcess}) => { console.log(adoptionProcess) // -> gives and empty array here return ( <Container> <Row className="adoptionContainer py-5"> <Col sm={12}> <h1>{adoptionProcess && adoptionProcess.adoptionProcessTitle.title}</h1> <Row className="mt-5 items"> {adoptionProcess && adoptionProcess.adoptionProcessItems.map((process) => ( <ProcessItems img={process.img} text={process.text} firstDescription={process.firstDescription} secondDescription={process.secondDescription} /> ))} </Row> </Col> </Row> </Container> ); }; export default ProcessContainer;
ProcessItems.js import React from "react"; import { Col } from "react-bootstrap"; import "./AdoptionProcess.css"; const ProcessItems = ({ img, text, firstDescription, secondDescription }) => { return ( <Col lg={4} className="mb-5"> <img src={img} alt="img" className="mb-3" /> <p>{text}</p> <span>{firstDescription}</span> <br /> <span>{secondDescription}</span> </Col> ); }; export default ProcessItems;
data.json { "adoptionProcessItems": [ { "id": 1, "img": "https://i.pinimg.com/736x/2e/23/d3/2e23d3827c8293c27cea544a8acbcd59.jpg", "text": "Find Your Pet", "firstDescription": "Lorem Ipsum Lorem Ipsum Lorem", "secondDescription": "Lorem Ipsum Lorem Ipsum Lorem" }, { "id": 2, "img": "https://i.pinimg.com/736x/5f/80/85/5f80854fd1475958717a19e345695942.jpg", "text": "Find Your Pet", "firstDescription": "Lorem Ipsum Lorem Ipsum Lorem", "secondDescription": "Lorem Ipsum Lorem Ipsum Lorem" }, { "id": 3, "img": "https://i.pinimg.com/736x/2e/23/d3/2e23d3827c8293c27cea544a8acbcd59.jpg", "text": "Find Your Pet", "firstDescription": "Lorem Ipsum Lorem Ipsum Lorem", "secondDescription": "Lorem Ipsum Lorem Ipsum Lorem" } ], "adoptionProcessTitle" : { "title" : "Pet Adoption Process" } }
Advertisement
Answer
There are multiple mistakes, you have in your code.
- Data returns object so please add initial state as an object.
const [adoptionProcess, setAdoptionProcess] = useState({});
- Adding async operation required loading flag
useEffect(() => { (async () => { const data = await fetchAsync(); setAdoptionProcess(data); setLoading(false); })(); }, []);
Why do I need to add a loading flag?
Because when your async operation is going on your processContainer
will get the {}
empty object as your adoption process and now you are accessing the adoptionProcess.adoptionProcessTitle.title
but the adoptionProcess
is empty so you are accessing the undefined of title and you got the same error in your response.
After the async operations are finished the state will be set and it causes the rerender and your processContainer
will get your data.json
data and you will get the results.
so the problem is your initial state and you can handle it using loading
flag
Please check this https://codesandbox.io/s/eager-jackson-m8odq?file=/src/App.js