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;
Related
categories name
pic of datas
import {useState, useEffect,useMemo} from 'react';
import { gql, useQuery } from '#apollo/client';
import {GET_CLOTHES} from "./GetClothes.js"
import ArrowForwardIosIcon from '#mui/icons-material/ArrowForwardIos';
import ArrowBackIosNewIcon from '#mui/icons-material/ArrowBackIosNew';
function Clothes() {
const { loading, error, data } = useQuery(GET_CLOTHES);
const [products,setProducts] = useState([]);
const [index,setIndex] = useState(0);
useEffect(() => {
if (data) {
setProducts(data.categories.products);
console.dir(data.categories.products);
}
},[data]);
//console.dir(products);
/*
useEffect(() => {
if(!loading && data){
setProducts(data);
}
}, [loading, data])
*/
if (loading) return 'Loading...'
if (error) return `Error! ${error.message}`
return <div>
{
// Products is actually products
products?.map((product,index) => {
if (product.name === 'clothes') { //filter
// Iterate through products.products to obtain the product data.
const {name,brand,description,gallery,category} = product;
return <p>{name}</p>
}})
}
</div>
}
export default Clothes;
`
Hello everyone, I am trying to fetch my datas from graphlq however I can fetch to first data from array but when I try reach one of the nested array I got undefined.
How I can solve this issue.
You don't need to keep data as a state variable
data will be undefined until loading is false. The first pass through your console.log it will be undefined.
A typical pattern might be:
function Clothes() {
const { loading, error, data } = useQuery(GET_CLOTHES);
if (data) {
… render the data
} else if (error) {
…handle the error
return <Error /> // return an error component
} else return <Loading /> // return a spinner or other progress indicator
}
Note that your function must return a jsx component - it cannot return a string.
Ok. First of all, categories is an array, so products isn't defined as a property in the array. Its items do have the products property.
Second of all, products is a derived state. You do not need make a separate it as its own useState
import {useState, useEffect,useMemo} from 'react';
import { gql, useQuery } from '#apollo/client';
import {GET_CLOTHES} from "./GetClothes.js"
import ArrowForwardIosIcon from '#mui/icons-material/ArrowForwardIos';
import ArrowBackIosNewIcon from '#mui/icons-material/ArrowBackIosNew';
function Clothes() {
const { loading, error, data } = useQuery(GET_CLOTHES);
const [index,setIndex] = useState(0);
if (loading) return 'Loading...'
if (error) return `Error! ${error.message}`
return <div>
{
data.categories.flatMap(x => x.products).map(product => {
if (product.name === 'clothes') { //filter
// Iterate through products.products to obtain the product data.
const {name,brand,description,gallery,category} = product;
return <p>{name}</p>
} else {
return null;
}
})
}
</div>
}
export default Clothes;
I'm getting myself confused with React here (total newbie). I have a simple component that fetches some data that always returns {"score":100}:
import React, { useEffect, useState } from "react";
import Graph from "./Graph.js";
const UsingFetch = () => {
const [results, setResults] = useState({"score": null}); // initially set score to null
const fetchData = () => {
fetch("https://myapi.com/id=1")
.then((response) => {
return response.json();
})
.then((data) => {
setResults(data); // update results with integer score
});
};
useEffect(() => {
fetchData();
}, []);
console.log(results)
return (
<div>
<Graph results={results.score}></Graph>
</div>
);
};
export default UsingFetch;
My Graph.js looks like the following:
import { React } from 'react'
export default function Graph({results}) {
console.log(results)
return (
<div>
<h1>{results}</h1>
</div>
)
}
Why doesn't the score render on the page? I've confirmed that the data returns correctly, I just can't seem to access it right.
Here's the console output:
Results is an array.
<h1>{results.map((result) => (result.score)}</h1>
I used axios in useEffect of my wrapper component and I sent the data as props to the other component "singleQuestionnaire", in singleQuestionnaire component, I destructured the data, in the first try, it works fine, but after reloading the page it doesn't work with an error : can not read property "map" of undefined
import React, { useEffect, useState } from "react";
import SingleQuestionnaire from "./SingleQuestionnaire";
import { fetchQuestions } from "../../../api/index";
const Questionnaires = ({ match }) => {
const [questions, setQuestions] = useState([]);
const pid = match.params.id;
const getQuestionnaire = async (pid) => {
try {
const { data } = await fetchQuestions(pid);
console.log(data.data, "action in component");
setQuestions(data.data);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getQuestionnaire(pid);
}, []);
console.log("all questions", questions);
return (
<div>
<SingleQuestionnaire questions={questions} setQuestions={setQuestions} />
</div>
);
};
export default Questionnaires;
and this is my singleQuestionnaire component:
import React, { useEffect, useState } from "react";
const SingleQuestionnaire = ({ questions, setQuestions }) => {
const [questionnaire, setQuestionnaire] = useState([]);
console.log(questions);
const { data } = questions;
console.log("data", data.farmInformationQuestionnaireData);
return <div>simple component</div>;
};
export default SingleQuestionnaire;
For the first time, in console I can see the data "data.data.farmInformationQuestionnaireData". It's an array but for the second time it's undefind.
because questions in SingleQuestionnaire is an empty array before we fetch
which causes an error here
const { data } = questions;
you can add a loading text because initially questions will be an empty array then it will be your res.data (assuming it's an object)
const SingleQuestionnaire = ({ questions, setQuestions }) => {
const [questionnaire, setQuestionnaire] = useState([]);
console.log(questions);
if(questions.length === 0 ) return <h1> Loading</h1>
const { data } = questions;
console.log("data", data.farmInformationQuestionnaireData);
return <div>simple component</div>;
};
it is happening because of the async API call. When you make an async call, the thread does not wait, it moves on and it starts executing other things.
Now your async call might be complete but your callback will not be executed until the stack is empty, that's just how javaScript works. I recommend you use some kind of loader gif or text
{questions ? <SingleQuestionnaire questions={questions} setQuestions={setQuestions} /> : <p>Loading...</p>}
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 am using Easy Peasy State management for React. I would like to create multiple Axios call from one store location and import it in each page there where I need to show the correct data. I am trying to fetch a JSON placeholder data for example and use that inside a component to push it to the state using Hooks.
But I get the following error:
model.js:14 Uncaught (in promise) TypeError: actions.setTodos is not a function
at model.js:14
Can someone help me out? What am I doing wrong?
My code for the store (model.js):
import { thunk } from 'easy-peasy';
export default {
todos: [],
fetchTodos: thunk(async actions => {
const res = await fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=10'
);
const todos = res.json();
actions.setTodos(todos);
}),
};
My Page component Contact:
import React, { useState, useEffect } from 'react';
import { useStoreActions } from 'easy-peasy';
import ReactHtmlParser from 'react-html-parser';
import { API_URL } from 'constants/import';
// import axios from 'axios';
const Contact = () => {
const [contactPage, setContactPage] = useState([]);
const { page_title, page_content, page_featured_image } = contactPage;
const fetchTodos = useStoreActions(actions => actions.fetchTodos);
useEffect(() => {
fetchTodos();
}, []);
return (
<section className="contact">
<div className="page">
<div className="row">
<div className="col-xs-12">
<h3 className="section__title">{page_title}</h3>
{ReactHtmlParser(page_content)}
{page_featured_image && (
<img src={API_URL + page_featured_image.path} />
)}
</div>
</div>
</div>
</section>
);
};
export default Contact;
You need to use action.
import { action, thunk } from "easy-peasy";
export default {
fetchTodos: thunk(async (actions, payload) => {
const res = await fetch(
"https://jsonplaceholder.typicode.com/todos?_limit=10"
);
const todos = res.json();
actions.setTodos(todos);
}),
todos: [],
setTodos: action((state, payload) => {
console.log("---->>> payload!")
state.todos = payload
}),
};
I usually use it like this, it works perfectly for me.