I don't really understand why, if I use asyn await directly to call api and I get data immediately when the component mount inside useEffect(), but when I call getLevels() from my selectApi.js, it return undefined when the component mount. See code below:
App.js
import axios from "axios";
import React, { useEffect, useState } from "react";
import { getLevels } from "./selectApi";
export default function App() {
const [options, setOptions] = useState([]);
useEffect(() => {
loadLevels();
}, []);
const loadLevels = async () => {
//Working fine if I use call await API directly in this file
const res = await axios.get("http://localhost:3040/v2/feedback/levels");
console.log("Data ----> ", res); //working fine
setOptions(res.data)
/* Not working if I import getLevels() from selectApi.js
getLevels().then((res) => {
console.log("Data --> ", res); //return Data --> Undefined when component load
});*/
};
return (
<div className="App">
<h1>Hello Select</h1>
<select>
<option value="">Please select</option>
{options.length > 0 &&
options.map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
</select>
</div>
);
}
SelectApi.js
const ENDPOINT_URL = "http://localhost:3040/v2/feedback/";
export const getLevels = async () => {
await axios.get("http://localhost:3040/v2/feedback/levels");
};
Working fine when I call api directly in App.js
Try this in selectApi.js
export const getLevels = async () => {
return await axios.get("http://localhost:3040/v2/feedback/levels");
};
Related
I am using multi avatar api to render random images on the UI, but I am getting the below-mentioned error. I also tried using promises to render the UI but failed to get the results.
Uncaught TypeError: The first argument must be one of type string,
Buffer, ArrayBuffer, Array, or Array-like Object. Received type
undefined
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import axios from "axios";
import { profilePicRoute } from "../utils/apiRoutes";
import { Buffer } from "buffer";
function ProfilePic() {
const api = "https://api.multiavatar.com";
const navigate = useNavigate();
const [profilePic, setProfilePic] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedPofilePic, setSelectedPofilePic] = useState(undefined);
const toastStyles = {
position: "top-center",
};
const setProfilePicture = async () => {};
useEffect(() => {
const data = [];
for (let i = 0; i < 4; i++) {
const image = axios.get(`${api}/${Math.round(Math.random() * 1000)}`);
const buffer = Buffer(image.data);
data.push(buffer.toString("base64"));
console.log(data);
}
setProfilePic(data);
setIsLoading(false);
}, []);
return (
<div className="profilePage">
<h1>Pick your favorite profile picture</h1>
<div className="profilePics">
{profilePic.map((pic, index) => {
return (
<div
key={index}
className={`pic ${selectedPofilePic === index ? "selected" : ""}`}
>
<img
src={`data:image/svg+xml;base64,${pic}`}
alt="profile pic"
onClick={() => setSelectedPofilePic(index)}
/>
</div>
);
})}
</div>
<ToastContainer />
</div>
);
}
export default ProfilePic;
Since you were using the async you must have to use await keyword , otherwise it will return promises,and you should use the function inside the useEffect
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import axios from "axios";
import { profilePicRoute } from "../utils/apiRoutes";
import { Buffer } from "buffer";
function ProfilePic() {
const api = "https://api.multiavatar.com";
const navigate = useNavigate();
const [profilePic, setProfilePic] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedPofilePic, setSelectedPofilePic] = useState(undefined);
const toastStyles = {
position: "top-center"
};
useEffect(() => {
const setProfilePicture = async () => {
const data = [];
for (let i = 0; i < 4; i++) {
const image = await axios.get(
`${api}/${Math.round(Math.random() * 1000)}`
);
console.log(image);
const buffer = Buffer(image.data);
data.push(buffer.toString("base64"));
}
setProfilePic(data);
setIsLoading(false);
};
setProfilePicture();
}, []);
return (
<div className="profilePage">
<h1>Pick your favorite profile picture</h1>
<div className="profilePics">
{profilePic.map((pic, index) => {
return (
<div
key={index}
className={`pic ${selectedPofilePic === index ? "selected" : ""}`}
>
<img
src={`data:image/svg+xml;base64,${pic}`}
alt="profile pic"
onClick={() => setSelectedPofilePic(index)}
/>
</div>
);
})}
</div>
<ToastContainer />
</div>
);
}
export default ProfilePic;
Hope this code will help you.
Happy Coding :)
I am trying to convert the fetch API to axios with get method.
Prior to do this, I plan to keep using 'async, await'.
And when I replaced the code below:
// before
const fetchPlanets = async () => {
const res = await fetch("http://swapi.dev/api/planets/");
return res.json();
};
// after
const fetchPlanets = async () => {
const res = await axios
.get("http://swapi.dev/api/planets/")
.then((respond) => {
respond.data;
});
};
async can be used when to address the function.
and returned const res as res.json();
Also...axios does not require to res.json as it returned as json type.
That's how I understand this so far. And with fetch API, this work flawlessly.
How the code should be to let axios work as I expected?
// Planets.js
import React from "react";
import { useQuery } from "react-query";
import Planet from "./Planet";
// import axios from "axios";
const fetchPlanets = async () => {
const res = await fetch("http://swapi.dev/api/planets/");
return res.json();
};
const Planets = () => {
const { data, status } = useQuery("planets", fetchPlanets);
console.log(data);
return (
<div>
<h2>Planets</h2>
{status === "loading" && <div>Loading data...</div>}
{status === "error" && <div>Error fetching data!</div>}
{status === "success" && (
<div>
{data.results.map((planet) => (
<Planet key={planet.name} planet={planet} />
))}
</div>
)}
</div>
);
};
export default Planets;
And Planet.js; just in case.
import React from "react";
const Planet = ({ planet }) => {
return (
<div className="card">
<h3>{planet.name}</h3>
<p>Population - {planet.population}</p>
<p>Terrain - {planet.terrain}</p>
</div>
);
};
export default Planet;
There are 2 problems in your axios code.
You should return respond.data.
You should return the whole axios response.
So this would work:
const fetchPlanets = async () => {
return await axios
.get("http://swapi.dev/api/planets/")
.then((respond) => {
return respond.data;
});
};
Here I've fetched workouts from backend through api. It shows output in the console but unable to map through workouts state in the webpage.
import React, { useEffect, useState } from "react";
const Home = () => {
const [workouts, setWorkouts] = useState([]);
useEffect(() => {
const fetchWorkouts = async () => {
const response = await fetch("http://localhost:4000/api/workouts");
const json = await response.json();
if (response.ok) {
console.log('success');
console.log(json);
setWorkouts(json);
}
};
fetchWorkouts();
}, []);
return (
<div className="home">
<div className="workouts">
{workouts &&
workouts.map((workout) => {
<p key={workout._id}>{workout.title}</p>;
})}
</div>
</div>
);
};
export default Home;
You forgot to return it. Do this:
return <p key={workout._id}>{workout.title}</p>;
or you can also do this:
{workouts?.map((workout) => (
<p key={workout._id}>{workout.title}</p>
))}
You can remove the bracket on the map:
workouts.map((workout) =>
<p key={workout._id}>{workout.title}</p>;
)}
You're not returning anything. Either explicitly use the return keyword to return the element or You can do this in a more appropriate way like this.
{
workouts &&
workouts.map((workout) => (
<p key={workout._id}>{workout.title}</p>
))
}
On this case I am trying to show the "_id".
I made the code based on this video.
But by just looking at his API I can see that his data is little different, how can I adapt it to work with my API
import "./App.css";
import axios from "axios";
import { useEffect, useState } from "react";
const App = () => {
const [leitura, setLeitura] = useState([]);
const getLeituraData = async () => {
try {
const data = await axios.get(
"https://estufaarduino.herokuapp.com/sistema/leituras"
);
console.log(data.data);
setLeitura(data.data);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getLeituraData();
}, []);
return (
<div className="App">
{leitura.map((item) => {
return <p>{item._id}</p>;
})}
</div>
);
};
export default App;
But there is no request to the server. Is there any mistakes in this code?
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom'
import axios from 'axios';
import { useSelector, useDispatch } from 'react-redux';
import { listProducts } from '../actions/productActions';
function HomeScreen(props) {
const productList = useSelector(state => state.productList);
const { products, loading, error } = productList;
const dispatch = useDispatch();
useEffect(() => {
const fetchData = async () =>{
dispatch(listProducts());
}
return () =>{
//
};
}, [])
return loading ? <div>Loading...</div> :
error ? <div>{error}</div> :
<ul className="products">
{
products.map(product =>
<li key={product._id}>
<div className="product">
<Link to={'/product/' + product._id}>
<img className="product-image" src={product.image} alt="product"/>
</Link>
<div className="product-name">
<Link to= {'/product/' + product._id}> {product.name} </Link>
</div>
<div className="product-brand">{product.brand}</div>
<div className="product-price">Rs.{product.price}</div>
<div className="product-rating">{product.rating} Stars ({product.numReivews}Reviews)</div>
</div>
</li>)
}
</ul>
}
export default HomeScreen;
As you see in following screenshot, there is no request to the server.Does anyone have idea about this matter?
You're not calling the fetchData() function. Instead you've only declared it inside useEffect.
So instead of
useEffect(() => {
const fetchData = async () =>{
dispatch(listProducts());
};
return () =>{
//
};
}, [])
you can just write
useEffect(() => {
dispatch(listProducts());
return () =>{
//
};
}, [])
This might not be the full solution as, for example, I don't know what listProducts() does but certainly it is a part of the solution.