Why my react-query request data won't show? - reactjs

This is my first time using react-query and I having problem request data from API.
This is the code:
import { useQuery } from "#tanstack/react-query";
import axios from "axios";
import "./App.css";
function App() {
const fetchData = async () =>{
const { data } = await axios.get("https://api.jikan.moe/v4/anime");
const response = data.data;
return response
}
const { isLoading,data,isError } = useQuery(
["posts"],
fetchData,
{
retry: false,
refreshInterval: 0,
staleTime: 0
}
);
if (isLoading) return <h1>...Loading</h1>;
if (isError) return <h1>Fail</h1>;
console.log(data)
return (
<div className="App">
{data.map((datas)=>{
<div>
{datas.title}
</div>
})}
</div>
);
}
export default App;
when I console.log(data) it does show the list of data Array of 25 object element.
But when I try the use data.map to show the data in the website nothing appear but It does appear if I only try the show one of the array like
{data[0].title}
the data does appear but when I try the show all array element with data.map but nothing seems to appear. Can someone help me?
thanks

the data does appear but when I try the show all array element with data.map but nothing seems to appear. Can someone help me?
Your Array#map does not return anything.
{data.map((datas) => {
return ( // return the JSX
<div>
{datas.title}
</div>
);
})}

Related

useEffect and useState to fetch API data

I want to use useEffect(on mount) to fetch from API and store it in useState. Fetch API is used to get the data. The problem is when initial page loading and also when I reload the page, it outputs an error called test.map is not a function. Why this happening and how to avoid this ?
import { useEffect, useState } from 'react';
function App() {
const[test, setTest] = useState({})
useEffect(() => {
testfunc()
}, [])
async function testfunc(){
let api = await fetch('https://jsonplaceholder.typicode.com/users')
let apijson = await api.json()
setTest(apijson)
}
return (
<div className="App">
{
test.map((item) => {
return(
<div>
{item.name}
</div>
)
})
}
</div>
);
}
export default App;
You can't map on an object {}, so you should need to define an array [] for the base state :
const[test, setTest] = useState([])
You have to change {} to array first to be able to map over it. You can easily place ? after test like this. or make in the default value of the state a default value for item name. because this error results as you map over an empty object.
import { useEffect, useState } from 'react';
function App() {
const[test, setTest] = useState([{name:"default"}])
useEffect(() => {
testfunc()
}, [])
async function testfunc(){
let api = await fetch('https://jsonplaceholder.typicode.com/users')
let apijson = await api.json()
setTest(apijson)
}
return (
<div className="App">
{
test?.map((item) => {
return(
<div>
{item.name}
</div>
)
})
}
</div>
);
}
export default App;
As already mentioned, you can't use the .map for objects.
Instead of this, you can make something like that
Object.keys(test).map(key => {
const currentSmth = test[key]
return(
<div>
{currentSmth.name}
</div>
)
})
})
I think it helps you to solve your problem.
Be careful using the correct data structures and methods.

React get value from key:value array

Beginner question. I know this is a simple question but I haven't been able to get this to work. I'm passing an object which holds an array of k:v pairs to a component. Eventually this props will contain multiple k:v pairs, but for now I'm just passing the one.
[{goal: 20000}]
In the component I'm trying to grab the value, 20000, so I can display it on screen. I can't seem to get just the number. If I look at props.goal I get the entire k:v.
[{goal: 20000}]
If I try props[0].goal I get 'TypeError: undefined is not an object (evaluating 'props[0].goal')'
What am I missing? Thanks for any help.
Update:
Here is the entire code for the component in question.
import { React, useState } from "react";
import Form from "react-bootstrap/Form";
import { Row, Col, Button } from "react-bootstrap";
import "./../css/Goal.css";
const Goal = (props) => {
// const [goal, setGoal] = useState("");
const [record, setRecord] = useState("");
const monthlyGoal = 2;
console.log("props[0]");
console.log(props[0]); //undefined
console.log("props");
console.log({ props }); //See below
props: Object
goal: Object
goals: [{goal: 20000}] (1)
const handleInput = (event) => {
console.log(event);
event.preventDefault();
setRecord(event.target.value);
console.log(record);
};
const defaultOptions = {
significantDigits: 2,
thousandsSeparator: ",",
decimalSeparator: ".",
symbol: "$",
};
const formattedMonthlyGoal = (value, options) => {
if (typeof value !== "number") value = 0.0;
options = { ...defaultOptions, ...options };
value = value.toFixed(options.significantDigits);
const [currency, decimal] = value.split(".");
return `${options.symbol} ${currency.replace(
/\B(?=(\d{3})+(?!\d))/g,
options.thousandsSeparator
)}${options.decimalSeparator}${decimal}`;
};
return (
<Form>
<Row className="align-items-center flex">
<Col sm={3} className="goal sm={3}">
<Form.Control
id="inlineFormInputGoal"
placeholder="Goal"
// onChange={(e) => setGoal(e.target.value)}
/>
<Button type="submit" className="submit btn-3" onSubmit={handleInput}>
Submit
</Button>
</Col>
<Col>
<h1 className="text-box">
Goal: {formattedMonthlyGoal(monthlyGoal)}
</h1>
</Col>
</Row>
</Form>
);
};
export default Goal;
Update 2:Here is the parent component:
import React, { useEffect, useState } from "react";
import Goal from "./Goal";
import axios from "axios";
const Dashboard = () => {
const [dashboardinfo, setdashboardinfo] = useState([]);
useEffect(() => {
async function fetchData() {
try {
const data = (await axios.get("/api/goals/getgoals")).data;
setdashboardinfo(data);
} catch (error) {
console.log(error);
}
}
fetchData();
}, []);
return (
<React.Fragment>
<Goal dashboardinfo={dashboardinfo} />
</React.Fragment>
);
};
export default Dashboard;
If you get an object like the following from console logging destructured props:
{
dashboardinfo: {goals: [{goal: 20000}]}
}
You need to use props.dashboardinfo.goals[0].goal to get the value.
Your props contains the object "dashboardinfo" so you need to do
props.dashboardinfo.goals[0].goal
or a better way is to destructure your props object like this
const Goal = ({dashboardinfo: { goals }}) => {
...
goals[0].goal
...
}
I believe I've resolved my issue. It wasn't so much a problem with accessing the key:value as I thought, because when the page was initialized I was able to grab the value and display it fine. However, when I refreshed the page I lost all of the props data and that resulted in an error. I tracked it down to the useState didn't seem to be updating the value before I was trying to read it. So I added a useEffect in the child component.
const Goal = (props) => {
const [goal, setgoal] = useState([]);
useEffect(() => {
setgoal(props.goal);
console.log("the goal", goal);
}, [props.goal, goal]);
...
This seems to have worked as I'm getting the information I want and not getting any errors when I refresh. This may not be the ideal way to go about this but it is working.

React async API call

I'm trying to understand somebody else code,
I have this component:
import React from 'react';
import { useEffect, useState } from 'react';
export default function CountriesList({ searchValue }) {
const [data, setData] = useState([])
//Onmount
useEffect(() => {
async function init() {
//API Calls- request data from the server
const response = await fetch('https://restcountries.com/v2/all');
const body = await response.json();
setData(body);
}
init()
}, [])//dependencies array
return (
<div className="countries-container">
{data
.filter(country => country.name.toLowerCase().includes(searchValue.toLowerCase()))
.map((country) => {
const { name, flag } = country;
return (
<div key={name} className="country-container">
<h3 className="title">{name}</h3>
<img src={flag} height="100px" width="100px" alt="flag" />
</div>
)
})}
</div>
)
}
inside init(), the programmer call init() again, can you explain why?
I tried to look for this style of programming and I didn't find anything.
whiteout this line the API call doesn't work.
thank you!
I may be mistaken, but as far as I can see, init function is declared and called right after declaration.
Check this out: https://github.com/facebook/react/issues/14326

How to map an array of maps from firestore in react

I'm trying to navigate an array of orders stored in each "User". I am able to query and find ones that have orders but I'm not able to display them. I keep getting an error "Cannot read property 'map' of null". Where am I going wrong?
The image below shows how all the orders are stored in "order"
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { firestore } from "../../../FireBase/FireBase";
const OrdersAdmin = (props) => {
const [order, setOrder] = useState(null);
useEffect(() => {
const fetchOrder = async () => {
const doc = await firestore.collection("Users");
const snapshot = await doc.where("orders", "!=", []).get();
if (snapshot.empty) {
console.log("No matching documents.");
return <h1>No Orders</h1>;
}
var ans = [];
snapshot.forEach((doc) => {
console.log(doc.id, "=>", doc.data().orders);
setOrder(doc.data().orders)
});
};
fetchOrder();
}, [props]);
return (
<div className="adminOrders">
<h1>orders</h1>
{console.log(order)}
{order.map((orderItem) => (
<div className="singleOrder" key={orderItem.id}>
<p>{orderItem}</p>
</div>
))}
</div>
);
};
export default OrdersAdmin;
The issue is that the initial value of order is null. null does not have Array.prototype.map, therefore you get the error. Try updating your render to use conditional rendering to only attempt Array.prototype.map when order is truthy and an Array:
{order && order.length > 0 && order.map((orderItem) => (
<div className="singleOrder" key={orderItem.id}>
<p>{orderItem}</p>
</div>
))}
Otherwise you can use a better default value of an empty array for order which would have Array.prototype.map available to execute:
const [order, setOrder] = useState([]);
Hopefully that helps!

React add comma one single string

I am using react app. I fetched one data from open api. in that api the ingredient in one single string but divided by \n1. When I fetched the data it came like this one single string and the \n1 shows like (, divided). I wanted to put the ingredients in the ul li elements or and comma-a after each ingredient. I tried lots of ways to split the data and also tried to add a comma after each word but it did not work. I shared my code in codesandbox.
This is my code
import React, { useEffect } from "react";
import "./styles.css";
export default function App() {
const [state, setState] = React.useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
const response = await fetch("https://sampleapis.com/recipes/api/recipes");
const data = await response.json();
setState(data);
};
return (
<div className="App">
{state.map((recipe) => {
return (
<>
<div key={recipe.id}>
<h1>{recipe.title}</h1>
<p>{recipe.ingredients}</p>
</div>
</>
);
})}
</div>
);
}
try to split and mapping them in separate html elements
<div className="App">
{state.map((recipe) => {
return (
<div key={recipe.id}>
<h1>{recipe.title}</h1>
<div>{recipe.ingredients?.split("\n").map(ingre=><p>{ingre}</p>)}</div>
</div>
);
})}
</div>
I found solution and did it like this:
const ingre = newRecipe.ingredients // this is the data
var result = ingre.split(',')
.map(word => `${word.trim()}`)
.join(', ');

Resources