Im trying to put a value that I get from axios on a div while I export that function
import React from 'react';
import axios from 'axios';
function callServer() {
axios.get(`http://localhost:${process.env.REACT_APP_SERVER_PORT}`, {
params: {
table: 'querotable',
},
}).then((response) => {
const resp = response.data;
console.log(resp);
return <div>{JSON.stringify(resp)}</div>;
});
}
export function SampleComponent() {
return (
<div>
{callServer()}
</div>
);
}
It shows nothing on div, only on console with the value that I want
Missing return
Your callServer function doesn't return anything. It doesn't even return a Promise. The statement return <div>{JSON.stringify(resp)}</div> is the return for the .then callback -- not for the function itself.
Use Component State
We could return a Promise that resolves to a div but that wouldn't be right. In order to handle asynchronous data in React we want to store that data to state.
const [resp, setResp] = useState();
Side Effects Go in useEffect
We also need to make sure that the axios.get function is only called once instead of on every re-render of SampleComponent. We can do that with a useEffect hook with an empty dependency array.
export function SampleComponent() {
const [resp, setResp] = useState();
useEffect(() => {
axios
.get(`http://localhost:${process.env.REACT_APP_SERVER_PORT}`, {
params: {
table: "querotable"
}
})
.then((response) => setResp(response.data));
}, []);
return (
<div>
<div>{JSON.stringify(resp)}</div>
</div>
);
}
Related
My goal is to map an array within a json object I'm calling from my API call with axios and fetchContext I had written for passing headers.
My problem, I can console.log the data but whenever I try to return the results array I get no list items.
My json from the console.log to get the results array:
{count: 4, results: Array(4)}
count: 4
results: (4) [{…}, {…}, {…}, {…}]
My ReactJS Component:
import React, { useState, useContext, useEffect } from 'react';
import { FetchContext } from '../context/FetchContext';
export const RandomPage = () => {
const fetchContext = useContext(FetchContext);
const [bookData, setBookData] = useState([]);
useEffect(() => {
const getData = async () => {
try {
const { data } = await fetchContext.authAxios.get('/dummylibrary/book/');
setBookData(data.bookData);
console.log(data);
} catch (err) {
console.log(err);
}
};
getData();
}, [fetchContext.authAxios]);
return (
<>
<ul>
{bookData &&
bookData.map((book) => (
<li key={book.id}>
{book.id}
</li>
))}
</ul>
</>
);
};
What did I miss or am not calling correctly in my React Component? My apologies in advance if this is a repeat, the answers out there didn't quite match up.
I was missing data.results in my setBookData. Thank you #Naren and #Drew Reese.
Getting undefined data type error while fetching data from JSON
I have searched at many places but didn't get the suitable answer
import SavedData from "./SavedData";
export default class Saved extends React.Component {
constructor() {
super();
this.state = {
loading: true,
datas: [],
};
}
async componentDidMount() {
const url = "https://todo-list-site.herokuapp.com/todo-data";
const response = await fetch(url);
const todoData = response.json().then((res) => {
this.setState({ datas: res });
});
}
render() {
console.log(this.state.datas[0].description); //not able to get data
return (
<div>
{/* {this.state.datas.map((items) => (
<SavedData
key={items.countTodo}
title={items.title}
desc={items.desc}
/>
))} */}
</div>
);
}
}
Someone help me so that I can proceed
Just like Dave Newton has pointed out in the comments, the render is triggered before the request completes. This is normal and you just need to handle it properly.
If you see the console logs of this codesandbox, you can see that initially this.state.datas is just an empty array [] - so any attempt to access this.state.datas[0].description will be undefined. Only after the state is updated when the request completes, the logs show the data retrieved - this is because according to the mount lifecycle of a React Component, the render() is called before the componentDidMount() and also the request being async.
This is very common and it is even recommended by the official React docs to make HTTP calls in componentDidMount(). The docs also has provided an example to handle this issue.
import SavedData from "./SavedData";
export default class Saved extends React.Component {
constructor() {
super();
this.state = {
loading: true, // we initially set this to true
datas: [],
};
}
async componentDidMount() {
const url = "https://todo-list-site.herokuapp.com/todo-data";
const response = await fetch(url);
const todoData = response.json().then((res) => {
this.setState({
datas: res,
loading: false // when the request is complete, we set this to false
});
});
}
render() {
if (this.state.loading) {
// during the first render, loading will be true and we
// can return a loading message or a spinner
return (
<div>Loading...</div>
);
}
// when render is called after the state update, loading will be false
// and this.state.datas will have the fetched data
console.log(this.state.datas[0].description);
return (
<div>
{this.state.datas.map((items) => (
<SavedData
key={items.countTodo}
title={items.title}
desc={items.desc}
/>
))}
</div>
);
}
}
Your datas state is initially an empty array until your componentDidMount fires and sets the state. As a result, your console log will then be undefined until the state is set. In order to combat this you must wait for this.state.datas[0] to be true before accessing the first objects description within the array. The following code seems to work as expected
import React from "react";
export default class Saved extends React.Component {
constructor() {
super();
this.state = {
loading: true,
datas: []
};
}
async componentDidMount() {
const url = "https://todo-list-site.herokuapp.com/todo-data";
const response = await fetch(url);
response.json().then((res) => {
this.setState({ datas: res });
});
}
render() {
console.log(this.state.datas[0] && this.state.datas[0].description);
return (
<div>
{this.state.datas.map((items, i) => (
<div key={i}>
<div> title={items.title}</div>
<div> desc={items.description}</div>
</div>
))}
</div>
);
}
}
I have data in json format and I want to loop through it to render the same component (ContentThumbnail) eight times but with different titles and other content.
I have tried creating a function which accepts four parameters to achieve this. Here is the function I've written in a separate file called RenderContent.js:
import React from 'react';
import ContentThumbnail from './ContentThumbnail';
function RenderContentThumbnail(data, sectionName, wrapperStart, wrapperEnd) {
return (
<div>
{data
.filter(d => d.sectionName === { sectionName })
.map(filteredSection => (
{wrapperStart}
<ContentThumbnail {filteredSection.title} />
{wrapperEnd}
))}
</div>
);
}
export default RenderContentThumbnail;
And here is where I'm trying to execute that function in my component DefaultDashboard.js:
import React, { useEffect } from 'react';
import RenderContent from '../../content-thumbnail/RenderContent';
const DefaultDashboard = () => {
const { data } = useFetchData({ queryString: `${contentLibraryApiUrl}/GetContentForPage/Home` });
return (
RenderContentThumbnail(data, "topSection", "<div>", "</div>")
);
};
export default DefaultDashboard;
Is anyone able to help me see where I'm going wrong? I'm getting errors inside my map function and the page won't render at all.:(
Many thanks!
Katie
UPDATE!
I have made a tweak to the code to specify the prop, which is called "title", but I'm getting the following:
You should change the way you are rendering RenderContent:
const DefaultDashboard = () => {
const { data } = useFetchData({ queryString: `${contentLibraryApiUrl}/GetContentForPage/Home` });
return (
<RenderContent data={data} sectionName="topSection" wrapperStart="<div>" wrapperEnd= "</div>")
);
};
You can make it a lot easier, removing RenderContentThumbnail:
const DefaultDashboard = () => {
const { data } = useFetchData({ queryString: `${contentLibraryApiUrl}/GetContentForPage/Home` });
return (
{data
.filter(d => d.sectionName === "topSection")
.map(filteredSection => (<div>
<ContentThumbnail title={filteredSection.title} />
</div>))
}
);
};
export default DefaultDashboard;
Good day guys, i'm having a little trouble trying to req data from axios and showing it up at ReactJS, i'm able to console.log the data, but when i try to render it at the page, it simply dot not appear, could someone please lend me a hand? i will let the code and a print of the console.log, it's probably a newbie mistake since i'm new to ReactJs and JSON, but i would be very grateful if someone could explain!
CODE:
import Image from 'next/image'
import { useRouter } from 'next/router'
import React, { Component, useState } from 'react'
import ReactDOM from 'react-dom'
import { useHistory ,useLocation } from 'react-router-dom';
import axios from 'axios'
const options = {
method: 'GET',
headers: {
'Authorization': 'OAuth oauth_consumer_key="key", oauth_signature_method="PLAINTEXT", oauth_signature="2CC8D92526EE859C90AABB1F09F3B719&"'}
};
class Page extends React.Component {
state= {
motorData: [],
opa: []
};
componentDidMount() {
const make = "fiat"
axios.get(`https://api.trademe.co.nz/v1/Search/Motors/Used.json?make=${make}`, options)
.then(res => {
const cars = res.data;
console.log(cars)
this.state.motorData.push(cars.List[0].StartPrice)
console.log(this.state.motorData)
})
}
render() {
return <div>
Data:{this.state.motorData}
</div>
}
}
export default Page ```
Thank you guys so much in advance!
Instead of doing a push to your state, you need to use setState. Something like this:
componentDidMount() {
const make = "fiat"
axios.get(`https://api.trademe.co.nz/v1/Search/Motors/Used.json?make=${make}`, options)
.then(res => {
const cars = res.data;
this.setState(state => ({
motorData: [...state.motorData, cars.List[0].StartPrice]
});
})
}
Also, your motorData is an array, right? so in your render method you might want to loop in that array because you won't be able to print it I think. You should do something like this:
render() {
return (
<div>
Data:
// Adjust the return to be what you want it to render and
// don't forget to add a `key` property to the element you
// will return
{this.state.motorData.map(data => data)}
</div>
)
}
The problem is that, to set the state correctly, you should use setState, in this way:
this.setState((state) => ({ motorData: [...state.motorData, cars.List[0].StartPrice]}))
Using setState tells React that the state is changed and it have to re-render the component.
I am using axios library to fetch data from a json file through json-server.
When I am loading and using the response object in a single component it is working perfectly. But when I am passing this response object to child component from parent component it is not loading the data. Also not receiving any errors, can someone please help me to understand the difference and what is wrong with my approach?
//Scenario-1 : working perfectly fine:
import React, { useState, useEffect } from 'react';
import Display from './Display';
import Note from './note'
import axios from 'axios';
const App = () => {
const [notes, setNotes] = useState([])
const hook = () => {
axios.get('http://localhost:3001/notes')
.then(response => {
setNotes(response.data)
})
}
useEffect(hook, [])
return (
<div>
{notes.map(n => <Note key={n.id} note={n} />)}
</div>
)
}
export default App;
//Scenario-2 : Not working as expected, also no errors.
const Display = (props) => {
//Receiving data here, can see the values in console.
console.log('inside display, props.notex: ', props.notex);
const [notes, setNotes] = useState(props.notex);
//Blank object, why useState() method is not setting the value of "notes" from "props.notex".
console.log('inside display, notes: ', notes);
const generateRows = () => {
console.log('generateRows: ', notes)
return (
notes.map(n => <Note key={n.id} note={n} />)
)
}
return (
<div>
<ul>
{generateRows()}
</ul>
</div>
)
}
const App = () => {
const [notes, setNotes] = useState([])
const hook = () => {
axios.get('http://localhost:3001/notes')
.then(response => {
setNotes(response.data)
})
}
useEffect(hook, [])
return (
<div>
<Display notex={notes} />
</div>
)
}
export default App;
My guess is that useState is asynchronous, same as setState in Class components. Due to its async nature, you are not able to log anything - the log gets executed before the useState actually does anything.
If you really want to do it this way, you could initialize the value of the useState as an empty array and set up a useEffect hook, with the props.notex in your dependency array, something like this:
useEffect(() => {
if (props.notex) setNotes(props.notex)
}, [props.notex])
And then in the return
return (
<div>
<ul>
{notes.length && generateRows()}
</ul>
</div>
)
But you could just pass the props down from the parent to child without setting the state in the child component.
Hope this helps!