Okay, so I have a React app that loads JSON data using axios. The app uses useContext() for state management. themeContext.js houses the get request to the JSON file and context provider etc. App.js has the header section, therefore, useContext is being used to reference ThemeContext so that the data from the JSON file can be used in the JSX (title and subtitle).
The issue comes into play in Home.js. Home.js useContext as well to reference ThemeContext, however, unlike App.js, Home.js is using dot notion to access data e.g. data.homearticle.title. When I comment the JSX in Home.js the app renders in the browser but when I uncomment JSX in Home.js and refresh the page goes blank!
I'm not receiving any error messages. I have included "homepage": "." in package.json and changed BrowserRouter to HashRouter as suggested in another post but unfortunately neither has resolved the issue I am encountering.
App.js
import {HashRouter as Router, Routes, Route, Link} from 'react-router-dom';
import Home from './pages/Home'
import About from './pages/About'
import Posts from './pages/Posts'
import Error from './pages/Error'
import Aside from './components/Aside'
import Footer from './components/Footer'
import {ThemeContext} from './components/themeContext';
import {useContext} from 'react';
function App() {
const {data} = useContext(ThemeContext);
return (
<Router>
<header>
<div className="container container-flex">
<div className="site-title">
<h1>{data.title}</h1>
<p className="subtitle">{data.subtitle}</p>
</div>
<nav>
<ul>
<li><Link className="current-page" to="/">home</Link></li>
<li><Link to="/about">about me</Link></li>
<li><Link to="/posts">recent posts</Link></li>
</ul>
</nav>
</div>
</header>
<div className="container container-flex">
<Routes>
<Route path="/" element={<Home />}/>
<Route path="/about" element={<About />}/>
<Route path="/posts" element={<Posts />}/>
<Route path="*" element={<Error />}/>
</Routes>
<Aside />
</div>
<Footer/>
</Router>
);
}
export default App;
Home.js
import {useContext} from 'react';
import {ThemeContext} from '../components/themeContext';
const Home = () => {
const {data} = useContext(ThemeContext)
return (
<>
<main role="main">
<article className="article-featured">
<h2 className="article-title">{data.homearticle1.title}</h2>
<img className="article-image" src="/img/life.jpg" alt={data.homearticle1.alt}/>
<p className="article-info">{data.homearticle1.info}</p>
<p className="article-body">{data.homearticle1.body}</p>
<a className="article-read-more" href="https://www.github.com/evan">{data.homearticle1.anchor}</a>
</article>
<hr>
</hr>
</main>
</>
)
}
export default Home
themeContext.js
import {useState, useEffect, createContext} from 'react'
import axios from 'axios'
const ThemeContext = createContext()
const ThemeContextProvider = props => {
const [data, setData] = useState({});
useEffect(() => {
axios.get('data.json')
.then(res => setData(res.data))
.catch(err =>console.log(err))
},[])
return (
<ThemeContext.Provider value={{data}}>
{props.children}
</ThemeContext.Provider>
)
}
export {ThemeContextProvider, ThemeContext}
data.json
{
"title": "Living the simple life",
"subtitle": "a blog exploring minimalism in life",
"homearticle1": {
"title": "Finding simplicity in life",
"image": "./img/life.jpg",
"alt": "Clock plant and lamp on a desk",
"info": "Feburary 21, 2022",
"body": "\n <strong>Life can get complicated really quickly</strong>, but it doesn't have to be!\n There are many ways to simplify your life, <a class='article-link' href='#'> a few of which we've explored in the past</a>.\n This week we're taking a bit of a approach though, in how you can find simplicity in the life you already living.",
"anchor": "Continue Reading",
"comments": "3 comments"
},
"homearticle2": {
"title": "Keeping cooking simple",
"body": "\n Food is a very important part of everyone's life.\n If you want to be healthy, you have to eat healthy.\n One of the easiest ways to do that is to keep your cooking nice and simple.",
"anchor": "Continue Reading",
"image": "img/food.jpg",
"alt": "dumplings with chop sticks",
"info": "July 12, 2021",
"comments": "5 comments"
},
"homearticle3": {
"title": "Simple decoractions",
"body": "\n A home isn't a home until you've decorated a little.\n People either don't decorate, or they go overboard and it doesn't have the impact they were hoping for. \n Staying simple will help draw the eye where you want it to and make things pop like never before.",
"anchor": "Continue Reading",
"image": "img/deco.jpg",
"alt": "plant in water bowl",
"info": "June 15, 2021",
"comments": "9 comments"
},
"homearticle4": {
"title": "Simplicity and work",
"body": "\n Work is often a major source of stress.\n People get frustrated,it ruins their relationship with others and it leads to burnout. \n By keeping your work life as simple as possible, it will help balance everything out.\n ",
"anchor": "Continue Reading",
"image": "img/work.jpg",
"alt": "desk chair with a white table",
"info": "May 7, 2021",
"comments": "6 comments"
},
"about":{
"title":"My name is Evan and living the simple life saved my life",
"body": "<strong>I use to be 'spend-a-holic'</strong>. I would purchase so many things that I thought that I loved, but the truth was I couldn't even appreciate any of it because there was too much. Things were terrible, my priorities I had none!\n I was spending money that should have been invested in assests, but i was purchasing junk all while still living at home with my parents.\n Life wasn't good for me then."
},
"abouttopic1":{
"subtitle": "How I turned things around",
"body": "<strong>I was on the verge of a breakdown</strong>. I literally sold 90% of my possessions and moved into a small apartment.\n It wasn't easy at all, but everything around me was in such a place, I didn't know what else to do. Yet, it worked.\n"
},
"abouttopic2":{
"subtitle": "How I turned things around",
"body": "strong>I was on the verge of a breakdown</strong>. I literally sold 90% of my possessions and moved into a small apartment.\n It wasn't easy at all, but everything around me was in such a place, I didn't know what else to do.\n Yet, it worked."
},
"abouttopic3":{
"subtitle": "Now I live the simple life",
"body": "Now that I'm living a simple life, things are so much better. I'm less stressed, enjoying life and my family more,and I have more free time and gained financial literacy.\n With how much it turned my life around, <strong>I felt like I had no choice but to start sharing how I did it</strong>, and how others can benefit from living a simple life as well, which is why I started this site!"
},
"widgettitle1": "About Me",
"widgettitle2": "Recent Posts",
"image": "img/aboutme.jpg",
"alt": "author smiling",
"body": "I find life better, and I'm happier, when things are nice and simple.",
"widgetpost1": {
"title": "Keeping cooking simple",
"image": "img/food.jpg"
},
"widgetpost2": {
"title": "Simplicity and work",
"image": "img/work.jpg",
"alt": "dumplings with chop sticks"
},
"widgetpost3": {
"title": "Simple decorations",
"alt": "plant in water bowl",
"image": "img/deco.jpg"
},
"footer": {
"website": "Living the Simple Life",
"copyright": "Copyright 2022"
}
}
CodePudding user response:
Since the ThemeContext
is defining data
as an empty object as its initial state, accessing data.homearticle1.body
will break due to data.homearticle1
being undefined
(there's probably an error message in the DevTools Console itself).
I suggest you to check if data.homearticle1
exists before using it, as in:
const Home = () => {
const {data} = useContext(ThemeContext)
return (
<>
<main role="main">
<article className="article-featured">
<h2 className="article-title">{data.homearticle1 && data.homearticle1.title}</h2>
<img className="article-image" src="/img/life.jpg" alt={data.homearticle1 && data.homearticle1.alt}/>
<p className="article-info">{data.homearticle1 && data.homearticle1.info}</p>
<p className="article-body">{data.homearticle1 && data.homearticle1.body}</p>
<a className="article-read-more" href="https://www.github.com/jerrellbryant">{data.homearticle1 && data.homearticle1.anchor}</a>
</article>
<hr>
</hr>
</main>
</>
)
}
As you can see, we're always checking if data.homearticle1
exists (due to it being a nested object), so what you can do instead is early return your component with a loading state or such:
if (!data.homearticle1) {
return <div>Loading...</div>
}
return (
// Rest of the component...
// Here you won't have to check if `data.homearticle1` exists
)