I am trying to fetch data from external JSON and I was able to console.log it, so the fetch works, but I am having trouble to print the values.
JSON:
{
"data": {
"shoes": [
{
"types": [
{
"color": "pink",
}]
}]
}
I need to get access to the color (pink).
This is my fetch:
const shoesInformations = "json.url"
const [shoesData, setShoesData] = useState([]);
useEffect(() => {
getShoesInfo();
}, []);
const getShoesInfo = async () => {
try {
const response = await fetch(shoesInformations);
const jsonData = await response.json();
const { data } = jsonData;
setShoesData(jsonData);
console.log(data);
} catch (err) {
console.log(err);
}
};
And my attempt to print it:
<p>{shoesData.types.color}</p>
I do not need to map through the data just print the value one by one {shoesData.types.color[1]}
The main problem is that you assign the whole fetch response instead of only the shoes array within it to the shoesData state variable. Try this:
const [shoesData, setShoesData] = useState([]);
useEffect(() => {
getShoesInfo();
}, [getShoesInfo]);
const getShoesInfo = async () => {
try {
const response = await fetch(shoesInformations);
const jsonData = await response.json();
setShoesData(jsonData.data.shoes);
} catch (err) {
console.log(err);
}
};
and then when you want to present it first add a check for empty array or use the safe navigation operator. Either do (if you really want it hardcoded):
<p>{shoesData[0]?.types[0].color}</p>
<p>{shoesData[1]?.types[0].color}</p>
or more flexibly something like:
const getShoesRepresentation = () => {
if (shoesData.length > 0) {
return null;
}
else {
return (
<p>{shoesData[0].types[0].color}</p>
);
}
};
and then use {getShoesRepresentation()} in your rendering. This will handle the empty array case and you can extend it to handle iteration over all shoe objects that you need. I strongly suggest you use an iteration approach instead of hard-coding the data like that. You can safely use it by supplying shoeIndexes which contains only the indexes you want to present and then iterate over them and create a respective <p> for each.
shoesData.types.color[1] won't work, you only have 1 element, so your index must be 0:
shoesData.types.color[0]
Related
I know you can do the following
export async function getStaticProps({ params }) {
console.log(params)
const res = await fetch(`https://example.com/api-access/news/2021_autumn_home_style_tips`)
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
return {
props: { data }, // will be passed to the page component as props
}
}
however what if the last part depending on the news item a user presses needs to change.
https://example.com/api-access/news/2021_autumn_home_style_tips
https://example.com/api-access/news/2020_autumn_home_style_tips
https://example.com/api-access/news/2021_car
https://example.com/api-access/news/top_songs
How can I make a [slug].js page that allows me to run that slug url for example
https://myexample.com/news/top_songs
would fetch data from https://example.com/api-access/news/top_songs
I have tried
export const getStaticPaths: GetStaticPaths<{ slug: string }> = async () => {
console.log(params)
const res = await fetch('https://example.com/api-access/news/{slug}')
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
return {
props: { data }, // will be passed to the page component as props
}
}
But get this error
When retrieving a complex JSON object from chrome.storage.local the object is breaking.
mock.json
{
"ThingOne" : [
"a",
"b"
],
"ThineTwo" : [
"a",
"b"
],
"People" : {
"FamilyOne" : {
"AgeOne" : "3",
"AgeTwo" : "8"
}
},
"Hats" : ["blue", "red", "green"]
}
and I am fetching this file (correctly) using
fetch('./mock.json').then(response => {
console.log(response);
return response.json();
}).then(data => {
//data == the whole json file
var data2 = JSON.stringify(data);
chrome.storage.local.set({'StoredJson': data2});
//here this is the result of this code
//console.log(data2.ThingOne[0]);
//outputs => "a"
}).catch(err => {
console.log("Error Reading data " + err);
});
waitfunction();
chrome.storage.local.get('StoredJson', function(result) {
console.log("from get ------"); //outputs below
console.log(result); //{Data: ""{\"ThingOneOne\":[\"a\",\"b\"],\...
console.log(typeof result); //object
console.log(typeof result.ThingOne);//undefined
//https://imgur.com/OF7pVQQ
});
Why is it working when I fetch the object but not when I retrieve it. I have tried storing it after JSON.stringifying it. And I have tried to use it after JSON.parsing it which returns
VM6:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse ()
indicating that it is already a JS object.
I have tried using dot notation and bracket notaion it doesn't work. When I store it in the chrome console as var data = {//json here} it works. But not live. StackOverflow: Save json to chrome storage / local storage hasn't helped me. Picture of console
There are multiple problems in the code.
There's no need for JSON.stringify. Just store the data directly.
Both fetch and chrome.storage are asynchronous so your chrome.storage.local.get will run before the data is set and it won't see the correct data.
waitfunction(); won't wait for anything, it won't influence asynchronous code before it or afterwards.
chrome.storage.local.get('StoredJson', callback) reads the data into an object property named StoredJson i.e. you can read the value as result.StoredJson.
Overall, a proper modern solution is to switch to async/await:
(async () => {
try {
const data = await (await fetch('./mock.json')).json();
console.log('Fetched', data);
await writeStorage({StoredJson: data});
const {StoredJson} = await readStorage('StoredJson');
console.log('Stored', StoredJson);
} catch (err) {
console.log(err);
}
})();
function readStorage(key) {
return new Promise(resolve => {
chrome.storage.local.get(key, resolve);
});
}
function writeStorage(data) {
return new Promise(resolve => {
chrome.storage.local.set(data, resolve);
});
}
I have to fetch 2 api from backend, and try to get the result from this two. but, at the moment, the JSON result I get from the first API is object Array in JSON. I need to pass the id from first API(using setState) to second API for path variables. But when I do in my way, it fail to retrieve the data. Consider the code below:
componentDidMount(){
// console.log(loginEmail)
fetch(`http://localhost:9000/api/item/list`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({data: res.data});
}
)
})
const id = this.state.data.id;
fetch(`http://localhost:9000/api/item/photo/view/${id}`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({res});}
)
})
}
The problem is that fetch returns a Promise so, at the line
const id = this.state.data.id;
You do not have data populated yet.
You have to concatenate the two requests in a way like the following:
componentDidMount() {
fetch(`http://localhost:9000/api/item/list`)
.then((resp) => {
// return the id
})
.then((id) => {
fetch(`http://localhost:9000/api/item/photo/view/${id}`)
.then((resp) => {
// do what you need with the result
})
})
}
Fetch is asynchronous, which means javascript will
fetch data on the first call with no waiting, and continue
to the second fetch call where the id is not defined or Null.
In order to fix that you can use promises as follow
My code example
import React from "react";
class Home extends React.Component {
constructor() {
super();
this.state = {
res: [],
}
}
// http://jsonplaceholder.typicode.com/users
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res);
}
)
})
})
}
async componentDidMount() {
let data = await this.fetchData("http://jsonplaceholder.typicode.com/users");
console.log("data :", data);
let id = data[0].id;
console.log("Id :", id);
let newData = await this.fetchData(`http://jsonplaceholder.typicode.com/users/${id}`);
this.setState({ res: newData });
}
render() {
return (
<div>
Call API
</div>
)
}
}
export default Home
Adapted on your code
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res.data);
}
)
})
})
}
async componentDidMount() {
// console.log(loginEmail)
let data = await this.fetchData("http://localhost:9000/api/item/list");
let id = data.id;
let newData = await this.fetchData(`http://localhost:9000/api/item/photo/view/${id}`);
this.setState({ res: newData });
}
You need to make sure that each id gets its relevant results.
async componentDidMount() {
await fetch(`http://localhost:9000/api/item/list`)
.then(async (resp) => {
let req_ = resp.map((item)=>{
return await fetch(`http://localhost:9000/api/item/photo/view/${item.id}`)
})
let result = Promise.all(req_)
console.log(result)
})
}
I am currently working on a ReactJS project where I created my own JSON-api. I am trying to fetch a specific value in the array but all I get back is undefined, console.log gives me this: Array.
My fetch function is as follows:
_fetchData = async () => {
const response = await fetch('http://localhost:3000/stories');
const json = await response.json();
this.setState({
title: json.title,
thumbnail_img_url: json.thumbnail_img_url
});
}
Please learn basic programming first.
gives me this: Array.
You yourself said json is an array and trying to access its property with json.title. Please either use the first element of the array or revisit your flow and see what you actually want to do.
_fetchData = async () => {
try {
const response = await fetch('http://localhost:3000/stories');
const json = await response.json();
this.setState({
title: json[0].title,
thumbnail_img_url: json[0].thumbnail_img_url
});
catch (err) { console.error(err.toString()); }
}
I not undestand everything with javascript etc, I want to get my data returned by ma action redux but i'have a problem with my code.
const mapStateToProps = state => {
const group = state.groupReducer.group ? state.groupReducer.group : [ ]
return {
group
}
how i can get my data ?
When I try with that:
const mapStateToProps = state => {
const group = state.groupReducer.group.data.data[0] ? state.groupReducer.group.data.data[0] : [ ]
return {
group
}
And my goal is map around group
renderGroup = group => {
return group.map((groups => {
<div key={groups.data.data.id}>
//
</div>
}))
}
Sagas.js
export function* loadApiDataGroup() {
try {
// API
const response = yield
call(axios.get,'http://localhost:8000/api/group');
yield put(loadGroup(response))
} catch (e) {
console.log('REQUEST FAILED! Could not get group.')
console.log(e)
}
}
Action.js
export function loadGroup(data){ return { type: LOAD_GROUP, data }};
export function creatGroup(data){ return { type: CREATE_GROUP, data}};
// reducer
export default function groupReducer( state= {}, action = {}){
switch (action.type){
case LOAD_GROUP:
return {
...state,
group: action.data
}
case CREATE_GROUP:
return {
...state
}
default:
return state
}
thank you to help me
Try
const mapStateToProps = state => ({
group: state.groupReducer.group || []
});
Then you can use this.props.group in the component. Even though you might only want one thing in mapStateToProps, it's usually not directly returned like that.
If group is the response of an API request, you need to unpack data first, this is done in your async action creator (you will want to use redux-thunk or something similar):
const getGroup = () => async (dispatch) => {
dispatch({ type: 'GET_GROUP_REQUEST' });
try {
const { data } = await axios.get('/some/url');
dispatch({ type: 'GET_GROUP_SUCCESS', payload: data });
} catch (error) {
dispatch({ type: 'GET_GROUP_FAILURE', payload: error });
}
};