I have been working with next13 new fetching methods but keep getting an error "Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."
I look at other code example but seem to use similar logic I am lost as too what I am missing.
async function getData() {
const res = await fetch('https://jsonplaceholder.typicode.com/todos')
return res.json()
}
export default async function AccountPage(props) {
const table = await getData();
return (
<ul>
{table.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
when you declared res it was a promise that was not resolved when you tried to map over the table. I would look into some React fundamentals like component lifecycle and state.
import React, { useEffect, useState } from "react"
function AccountPage(props) {
const [table, setTableData] = useState(null)
const getData = () => {
fetch('https://jsonplaceholder.typicode.com/todos')
.then(res => res.json())
.then(data => {
setTableData(data)
})
}
useEffect(() => {
getData()
}, [])
return (
<div>
{table && <ul>
{table.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>}
</div>
)
}
export default AccountPage
Related
I am trying to manipulate the request from an api call and insert info into my jsx, but I get this error:
"Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."
I can see that it has something to do with this my jsx includes a promise, but I dont understand why.
import React from "react";
export default function Card_Container() {
return (
<div>
{fetch("http://localhost:1337/posts")
.then((res) => res.json())
.then((data) => {
data.map((post) => {
return <h1>{post.blogtitle}</h1>;
});
})}
</div>
);
}
As the error report, the jsx file can't render a object promise, try to do something like this:
import React, { useEffect, useState } from "react";
export default function Card_Container() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("http://localhost:1337/posts")
.then((res) => res.json())
.then((res) => {
setData(res);
});
}, []);
return (
<div>
{data.map((post) => {
return <h1>{post.blogtitle}</h1>;
})}
</div>
);
}
The useEffect is triggered once the component has been mounted, when the fetch call receive a response from the server the setState will store the information into data and the component will be rendered again, but this time if the response is correctly stored into data you should see a list of h1 in your application
Import React from "react";
export default function Card_Container() {
return (
<div>
{ fetch("http://localhost:1337/posts")
.then((res) => res.json())
.then((data) => {
data.map((post => {
<h1>{post.blogtitle}</h1>
))})};
</div>
);
}
The problem is not with the logic but syntax. => already works as a return so no need to add another.
Best Practice:
componentDidMount(){
console.log(">>>>> componentDidMount...");
url= 'http://localhost:1337/posts';
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
console.log(JSON.stringify(responseJson));
this.setState({result:responseJson});
return responseJson;
})
.catch((error) => {
console.error(error);
});
}
render() {
return(
<div>
{this.state.result.map(post => (
<h1>{post.blogtitle}</h1></div>))}
Widgets.js
import React, {useContext} from 'react';
import { DataContext } from '../contexts/DataContext';
const Widgets = () => {
const {updates} = useContext(DataContext);
console.log(updates);
return (
<div className="MainWidget">
<ul>
{updates.map(update => {
return (
<div>
<li>{update.current.condition}</li>
<p>{update.current.temp_c}</p>
</div>
);
})}
</ul>
</div>
);
}
export default Widgets;
I'm mapping data from an API which is returning an error: TypeError: updates.map is not a function but its actually returning the data in the console using the console.log() function.
DataContext.js
:I'm using axios to fetch data from weatherapi.com and setting the state 'updates' with 'setUpdates' function.
import React, {useState, useEffect, createContext} from 'react';
import axios from 'axios';
export const DataContext = createContext();
const DataContextProvider = (props) => {
const [updates, setUpdates] = useState({});
const url = "https://api.weatherapi.com/v1/current.json?key=931701d0de0c4d05b0b34936203011&q=London";
useEffect(() => {
axios.get(url)
.then(res => {
console.log(res.json())
setUpdates(res.data)
})
.catch(err => {
console.log(err)
})
})
return (
<div>
<DataContext.Provider value={{updates}}>
{props.children}
</DataContext.Provider>
</div>
)
}
export default DataContextProvider;
You're requesting data for only one location and the API returns you an object, not an array. You can either change your component to expect an object, or update the context provider, so it provides an array. That will looks something like:
const [updates, setUpdates] = useState([]);//note you want an array ([]) not an object ({})
...
let data = res.data
if(!data instanceof Array) data = [data] //put an object into array if needed
setUpdates(data)
UPDATE
In you repo make following changes:
In the DataContext you need to parse JSON response into an object, so replace
axios.get(url)
.then(res => {
setUpdates(res.data.current)
})
with
axios.get(url)
.then(res => res.json())
.then(res => {
setUpdates(res.current)
})
This will mean you already have current in the provider and in the component you can access its fields directly, so you'll need to replace
<p>{updates.current}</p>
with something like
<p>{updates.temp_c}</p>
<p>{updates.humidity}</p>
Not sure, but either your updates is an object, which means you can't map, or while your API is being called, that is undefined, which is why it crashes.
If your update is an object then you can do: map function for objects (instead of arrays)
If its undefined while calling API, then you can do a simple check to see if its undefined and only map when it's not.
I have fetched the top 30 teams in CSGO from the Hltv API. The data is stored inside the team variable and I use a map function in order to get the individual teams names from the array and render it. However, it currently is not rendering anything.
import React from 'react';
import './App.css';
import HLTV from 'hltv';
function App() {
const get = async () => {
return await HLTV.getTeamRanking()
.then(res => Object.entries(res))
.catch(err => console.log(err));
}
const teamNames = [];
(async () => {
const teams = await get();
teams.map(x => {
teamNames.push(x[1].team.name);
});
teamNames.map(team => {
console.log(team);
})
})();
return (
<ul>
{teamNames.map(team => <li>{team}</li>)}
</ul>
)
}
export default App;
React doesn't know that the teamMates variable is being updated. In order to let React know about a change in the variable, you should either fetch the data before rendering the component or use useState with useEffect.
You can read the useState documentation for more information.
import React, { useState, useEffect } from 'react';
import './App.css';
import HLTV from 'hltv';
const get = async () => {
return await HLTV.getTeamRanking()
.then(res => Object.entries(res))
.catch(err => console.log(err));
}
function App() {
const [teamNames, setTeamNames] = useState([]);
useEffect(() => {
get().then(teams => {
setTeamNames(teams.map(x => x[1].team.name));
});
}, []);
return (
<ul>
{teamNames.map(team => <li>{team}</li>)}
</ul>
)
}
It won't render because the results arrive too late for the initial render. Change teamNames to be stateful, e.g. const [teamNames, setTeamNames ] = useState([]). Then update the incoming result with setTeamNames. And instead of an IIFE (Immediately Invoked Function Expression), use useEffect(() => {...}).
For example:
function App() {
const [teamNames, setTeamNames] = useState([]);
React.useEffect(() => {
const fetchTeamRankings = async () => {
return HLTV.getTeamRanking()
.then(res => Object.entries(res))
.catch(err => console.log(err));
};
fetchTeamRankings().then(result => setTeamNames(result.map( r => r[1].team.name )));
}, [setTeamNames]);
return (
<ul>
{teamNames.map(team => <li>{team}</li>)}
</ul>
)
}
I am using React Hooks to get data from an existing API. Here is my code
import React, { useState, useEffect } from "react";
export const People = () => {
const [people, setPeople] = useState([]);
const url = "http://127.0.0.1:5000/people";
async function fetchData() {
console.log("calling api .. ");
const res = await fetch(url);
res.json().then((res) => setPeople(res));
}
useEffect(() => {
fetchData();
});
return (
<div>
<ul>
{people &&
people.map((person) => <li key={person.id}>{person.name}</li>)}
</ul>
</div>
);
};
const Dashboard = (props) => {
return (
<div>
<People />
</div>
);
};
export default Dashboard;
The problem that I am having is this API is getting called over and over again. Can you please let me know what I am doing wrong here.
Thanks
Currently, using useEffect(callback) will execute the callback on every render.
Try using useEffect with an empty dependencies array.
If you want to run an effect and clean it up only once, you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.
Check my other answer on useEffect use cases.
useEffect(() => {
fetchData();
}, []);
As for the rest of the component, it should look like so (opinioned):
// Should be on the outer scope as the URL is decoupled from the component's logic
const url = "http://127.0.0.1:5000/people";
export const People = () => {
const [people, setPeople] = useState([]);
useEffect(() => {
// This way fetchData won't re-assigned on every render
async function fetchData() {
console.log("calling api .. ");
const res = await fetch(URL);
// Consitstance, don't mix `then` and `await` syntax
const people = await res.json();
setPeople(people);
}
fetchData();
}, []);
return (
<div>
<ul>
{people &&
people.map((person) => <li key={person.id}>{person.name}</li>)}
</ul>
</div>
);
};
I have a function that makes a call to the server and retrieves data in a form of array of json objects, what i want is to iterate through the data and display them in the JSX .
Thw Problem is
No thing is being displayed on the screen, not even getting an error. and when I console.log the response i got this:
below is the component
import React from 'react';
import axios from 'axios';
function Supplier(){
let suppliers_list=[];
React.useEffect(() => {
getAllSuppliers();
});
const getAllSuppliers = () =>{
return axios.get('http://localhost:4000/supplier',supplierData).then(
response=>{
let allSuppliers = response.data;
allSuppliers.forEach(element => {
suppliers_list.push(
<li>{element.supplier_name}</li>
);
});
},error =>{
//handle error
}
);
}
return(
<div>
<ul>
{suppliers_list}
</ul>
</div>
)
}
export default Supplier;
and when I console.log the suppliers_list I got this:
Change your code like below,
import React from 'react';
import axios from 'axios';
function Supplier(){
const [suppliersList, setSuppliersList] = React.useState([]);
React.useEffect(() => {
getAllSuppliers();
}, []); // Hoping you want to execute getAllSuppliers function only once, so [] empty square braces
const getAllSuppliers = () =>{
return axios.get('http://localhost:4000/supplier', supplierData).then(
response=>{
setSuppliersList(response.data);
},error =>{
//handle error
}
);
}
return(
<div>
<ul>
{suppliersList.map(supplierObject => {
return <li>{supplierObject.supplier_name}</li>
})}
</ul>
</div>
)
}
export default Supplier;