Console log showing more than expected while using React Hooks - javascript

I am trying to fetch Data from an Api. I am getting the required result but when I try to console log it , it is console logging 4 times.
This is my app.js where I am using the fetchData.
import React, {useEffect, useState} from 'react';
import styles from './App.modules.css';
import {Header, Cards, Footer, Map, Table, Statecards} from './components/exports';
import {fetchData} from './api';
function App() {
const [data, setData] = useState({});
useEffect(() => {
const settingData = async () => {
const data = await fetchData();
setData(data);
}
settingData();
}, []);
console.log(data);
return <div className = {styles.container}>
<Header />
</div>
;
}
export default App;
This is the fetchData function
import axios from 'axios';
const url = 'https://api.covid19india.org/data.json';
export const fetchData = async () => {
try{
const response = await axios.get(url);
return response;
}
catch(err){
console.log(err);
}
};
The console.log in the app.js is giving 4 console logs as below
I am not being able to figure out what's wrong.

const settingData = async () => {
const data = await fetchData();
setData(data);
}
useEffect(() => {
settingData();
}, []);
try this one.

Related

why am I getting an error in fetching data here?

I have this for saving fetched data in state:
import React, {useState, useEffect, createContext} from 'react';
import { getLocation } from '../api';
export const LocationContext = createContext();
const LocatonContextProvider = (props) => {
const [location, setLocation] = useState({})
useEffect(() => {
const fetchAPI = async () => {
setLocation(await getLocation());
}
fetchAPI();
}, [])
return (
<LocationContext.Provider value={location}>
{props.children}
</LocationContext.Provider>
);
};
export default LocatonContextProvider;
and this for saving weather data
import React, {useState, useEffect, createContext, useContext} from
'react';
//api
import { getWeather } from '../services/api';
//Context
import { LocationContext } from '../contexts/LocationContextProvider';
export const WeatherContext = createContext()
const WeatherContextProvider = ({children}) => {
const location = useContext(LocationContext);
const lat = location.lat;
const lon = location.lon;
const [weather, setWeather] = useState({});
useEffect(() => {
const fetchAPI = async () => {
setWeather(await getWeather(lat,lon));
}
fetchAPI();
}, [lat, lon])
return (
<WeatherContext.Provider value={weather}>
{children}
</WeatherContext.Provider>
);
};
export default WeatherContextProvider;
and here is the axios request:
import axios from "axios";
const getLocation = async () => {
const LOCATION_URL = 'http://ip-api.com/json/?fields=country,city,lat,lon,timezone';
const response = await axios.get(LOCATION_URL);
return response.data;
}
const getWeather = async (lat, lon) => {
const WEATHER_URL = `https://api.openweathermap.org/data/2.5/weather?
lat=${lat}&lon=${lon}&appid=bac9f71264248603c36f011a991ec5f6`;
const response = await axios.get(WEATHER_URL)
return response.data;
}
export {getLocation, getWeather};
When I refresh the page, I get an 400 error and after that I get the data, I don't know why the error occurs
useEffect(() => {
const fetchAPI = async () => {
setWeather(await getWeather(lat,lon));
}
if (lat && lon) {
fetchAPI();
}
}, [lat, lon])

I want to fetch data and display it in a react page

I'm new to reactjs, I want to fetch and display data from my database table in a react page ,i wrote a code following a tutorial but i don't know how to correct it.
This is the data :
and this is the code i'm writing
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function Companies() {
const [companies, setCompanies] = useState(initialState: [])
useEffect( effect: () => {
companydata()
}, deps: [])
const companydata = async () => {
const {data}= await axios.get("http://localhost:5000/api/v1/companies");
setCompanies(data);
}
return (
<div className="companies">
{companies.map(companies => (
<div key={companies.CompanyId}>
<h5>{companies.CompanyName}</h5>
</div>
))}
</div>
);
}
export default Companies;
useEffect( effect: async () => {
await companydata()
}, deps: [])
have you tried adding async and await inside useEffect hook
Try to change your code like this:
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function Companies() {
const [companies, setCompanies] = useState([]);
useEffect(() => {
companydata();
}, []);
const companydata = async () => {
const { data } = await axios.get('http://localhost:5000/api/v1/companies');
setCompanies(data);
};
return (
<div className='companies'>
{companies.map((comp) => (
<div key={comp.CompanyId}>
<h5>{comp.CompanyName}</h5>
</div>
))}
</div>
);
}
export default Companies;

Why does it make a mistake?

The code below is not working. It doesn't see the apikey in parentheses.I couldn't understand what I had to do here. Is it a problem with the hooks structure?
import React, { useEffect } from 'react';
import MovieListing from "../MovieListing/MovieListing";
import movieApi from "../../common/apis/movieApi";
import { APIKey } from "../../common/apis/MovieApiKey"; //the program does not see this
import "./Home.scss";
import { useDispatch } from 'react-redux';
import { addMovies } from '../../features/movies/movieSlice';
const Home = () => {
const dispatch = useDispatch();
useEffect(() => {
const movieText = "Harry";
const fetchMovies = async () => {
const response = await movieApi.get('?apiKey=${APIKey}&s=${movieText}&type=movie')
.catch((err) => { console.log("Err :", err) });
dispatch(addMovies)(response.data); //api key does not see this
};
fetchMovies();
}, []);
return (
<div>
<div className='banner-img'></div>
<MovieListing />
</div>
);
};
export default Home;

Cannot setting the state with the data fetched in useEffect -React

I want to send an API request in useEffect hook and setting the state variables value with the fetched data. I added 2 console.log for detecting the state variables value. I except the second log to be setted with the fetched data, however it still prints null.
Here is my code:
import { useEffect, useState } from "react";
import axios from "axios";
const Test = () =>{
const [users, setUsers] = useState(null);
useEffect(()=>{
const getData = async ()=>{
const resp = await axios.get("https://jsonplaceholder.typicode.com/todos");
console.log(users);
setUsers(resp.data);
console.log(users);
};
getData();
},[])
return (
<div>hello</div>
)
};
export default Test;
Additionally the console output look likes this:
null
null
useState's setter is asynchronous, therefore your second console.log will be called before the users is actually updated.
For it to work, just put it outside the useEffect.
import { useEffect, useState } from "react";
import axios from "axios";
const Test = () =>{
const [users, setUsers] = useState(null);
useEffect(()=>{
const getData = async ()=>{
const resp = await axios.get("https://jsonplaceholder.typicode.com/todos");
console.log(users);
setUsers(resp.data);
};
getData();
},[])
console.log(users);
return (
<div>hello</div>
)
};
export default Test;
or in another dedicated useEffect, by passing users in the dependencies array.
import { useEffect, useState } from "react";
import axios from "axios";
const Test = () =>{
const [users, setUsers] = useState(null);
useEffect(()=>{
const getData = async ()=>{
const resp = await axios.get("https://jsonplaceholder.typicode.com/todos");
console.log(users);
setUsers(resp.data);
};
getData();
},[])
useEffect(()=>{
console.log(users);
},[users])
return (
<div>hello</div>
)
};

How can I mock return data from a custom hook in React/Jest?

I have a custom hook called useFetch which simply fetches data and returns it, in my component test I want to just mock this hook to return some fake data, how can I go about doing this?
import React, { useEffect, useState } from 'react';
export const useFetch = (url: string) => {
const [data, setData] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(url);
const json = await res.json();
setData(json);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [url]);
return data;
};
const App = () => {
const config = useFetch(`/api/url`);
return (
<div></div>
);
};
export default App;
Is there anyway I can mock useFetch so that const config is set to some dummy data in my Jest test?
I Will suggest to put your hook in separate file lets say useFetch.js conntains
import { useEffect, useState } from "react";
export const useFetch = (url: string) => {
const [data, setData] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(url);
const json = await res.json();
setData(json);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [url]);
return data;
};
Keeping your app component file like follows
import React from "react";
import { useFetch } from "./useFetch";
const App = () => {
const config = useFetch(`/api/url`);
return (
<div></div>
);
};
export default App;
with above split you can easily mock your hook, example test file as follows
import React from "react";
import { render } from "#testing-library/react";
import App from "./App";
// mock config
const mockConfig = {
data: "mock data"
};
// this will mock complete file, we have provided mock implementation
// for useFetch function
jest.mock("./useFetch", () => ({
useFetch: () => mockConfig
}));
test("should render with mock useFetch", () => {
const { getByText } = render(<App />);
// test logic goes here
});
Assuming all the files are in same directory.
You could try to mock the fetch library.
In the test setup:
global.fetch = jest.fn()
And then in your test:
global.fetch.mockResolvedValue({ json: () => ({ data: "" })})

Categories