I have a component in react that fetches a story that a user wrote from the backend. I then store the json in the storyState
and when I log it, the needed properties like "title" are in there, but when I try to access the property title, I get this error:
TypeError: Cannot read properties of undefined (reading 'title')
Here is the code:
import { useState, useEffect } from 'react';
import styled from 'styled-components';
export const StoryPage = () => {
const [storyState, setStoryState] = useState({
story: {},
isLoaded: false,
error: null,
});
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const id = urlParams.get('storyid');
useEffect(() => {
fetch('http://localhost:5000//getstory?storyid=' id)
.then((response) => {
console.log('response is', response);
if (response.status !== '200') {
let err = Error;
err.message = 'Invalid response code: ' response.status;
setStoryState({ error: err });
}
return response.json();
})
.then((json) => {
console.log('json is', json);
setStoryState({
story: json.story,
isLoaded: true,
});
});
}, []);
console.log('storystate.story', storyState.story);
return (
<>
<h1>test</h1>
<h1>{storyState.story.title}</h1>
</>
);
};
export default StoryPage;
I checked StackOverflow and tried using JSON.parse
, which didn't work unfortunately.
When I do < h1 >{storyState.story}</ h1 >
I get the whole object in string form with all the properties as expected.
Here is my console:
CodePudding user response:
Issue is at this line -
if (response.status !== "200") {
}
It should be 200 instead of "200". You can check the console.log("response is", response);
, it's numeric 200 not string.
Note: Always use the below construct to setState for objects -
{ ...previousState, { newkey: newvalue } }
The above uses the previous values of object and replaces with new values.
CodePudding user response:
In the very first render, data is not available, hence you have to render
<h1>{storyState.story.title}</h1>
only when the data is fetched and available so add an if statement in the render or you can use optional chaining too
<h1>{storyState?.story?.title}</h1>
CodePudding user response:
There could be a delay in fetching data from server, you can add a loader in it which checks if there is a value in storySTate
then render the data or add another useEffect function which logs file whenever there is a change in storyState hook eg:
useEffect(() => {
console.log(storyState.story)
}, [storyState])