useEffect not refreshing or Triggering on Adding New Friends - reactjs

const {Account,flag,setfriends} = useContext(AccountContext);
const [text,settext] = useState('');
useEffect(()=>{
const get = async() => {
// if(friends.length !== 0) return
const res = await getFriends(Account._id);
const data = res.data?.friends;
const filterData = data.filter(ele=>ele.name.toLowerCase().includes(text.toLowerCase()))
setfriends(filterData);
}
get(); //want to refetch data when new friend added
// eslint-disable-next-line
},[flag,text]);
//User.jsx
const {setperson} = useContext(PersonContext);
const {Account,flag,setflag} = useContext(AccountContext);
const add = async() => {
const data = {
user:userinfo,
info,
}
await addFriend(data);
setflag(!flag); **changing context flag which will recall upper useEffect but not callingi it
};
plese help me to Recall the upper useEffect it is not calling again when context flag changes
// AccountContext.jsx
import React,{createContext, useState,useRef,useEffect} from 'react'
import {io} from 'socket.io-client';
export const AccountContext = createContext(null);
const AccountProvider = ({children}) => {
const socket = useRef();
const [Account,setAccount] = useState();
const [activeUsers,setactiveUsers] = useState([]);
const [flag,setflag] = useState(false);
const [friends,setfriends] = useState([]);
useEffect(()=>{
socket.current = io('ws://localhost:8000')
},[])
return (
<AccountContext.Provider value={{Account,setAccount,activeUsers,setactiveUsers,flag,setflag,socket,friends,setfriends}}>{children}</AccountContext.Provider>
)
}
export default AccountProvider
These is Account Provider where i have saved freinds list

Related

I want to fetch weather data based on the users geolocation. Thought I had this figured out but I don't

I'm sure this has to do with the timing geolocation and axios fetching the data. With useEffect
it will give the wrong location. If I call the function without useEffect I will get the correct location but this creates an infinite loop. I've also tried using a condition in the useEffect.
and have tried using setTimeout;
How do I make sure navigator.geolocation has the lat and long before fetching the data?
import React from 'react';
import { useState, useEffect } from 'react';
import './css/weather.css'
import axios from 'axios';
const Weather = () => {
const [lat, setLat] = useState(0);
const [long, setLong] = useState(0);
const [temp, setTemp] = useState(0);
const [wind, setWind] = useState('');
const [windDir, setWindDir] = useState('');
const [gust, setGust] = useState('');
const [precip, setPrecip] = useState(0);
const [icon, setIcon] = useState('');
const [pic, setPic] = useState('');
const [city, setCity] = useState('');
const getWeather = async () => {
try {
await navigator.geolocation.getCurrentPosition((position) => {
setLat(position.coords.latitude);
setLong(position.coords.longitude);
})
const response = await axios.get(`http://api.weatherapi.com/v1/current.json?key=6e6263afb84f44279f731543222510&q=${lat},${long}&aqi=no`);
console.log(response.data)
setCity(response.data.location.name)
setTemp(response.data.current.temp_f);
setWind(response.data.current.wind_mph);
setWindDir(response.data.current.wind_dir);
setGust(response.data.current.gust_mph);
setPrecip(response.data.current.precip_in);
setPic(response.data.current.condition.icon.slice(-7))
if(response.data.current.condition.icon.includes('day')){
setIcon(<img src={`/assets/weather/64x64/day/${pic}`}></img>
)
} else {
setIcon(<img src={`/assets/weather/64x64/night/${pic}`}></img> )
}
} catch (err) {
console.error(err)
}
}
useEffect(() =>{
getWeather();
},[])
return (
<div className='weather-container'>
<p>{icon}</p>
<h2>{city}</h2>
<p>{`Current Temp: ${Math.round(temp)} °F`}</p>
<p>{`Wind: ${windDir} ${Math.round(wind)} mph Gusts: ${Math.round(gust)} mph`}</p>
<p>{`Precip: ${Math.round(precip)}in`}</p>
</div>
)
}
export default Weather;
I think I have found the solution. Putting lat in useEffect as an dependency seems to have solved the problem.
useEffect(() => {
getWeather();
}, [lat]);

Reducer 400 bed request on refresh page how can i solve

const DashboardPage = (props) => {
const userData = useSelector((state) => state.userDataReducer.user_record_reducer)
console.log('userdata', userData);
const adm_id = userData.adm_id
const [vistLoader, setVisitLoader] = useState(false)
const drid = localStorage.getItem('drId')
const [dashboard, setDashboard] = useState({})
const [collapsed,setCollapased] = useState(false);
const mr = userData.mrno
useEffect(()=>{
setVisitLoader(true)
const dashboard = getPatientDashboard({mr,drid}).then(res =>{
setDashboard(res)
setTimeout(()=>{
setVisitLoader(false)
}, 500)
}).catch(err =>{
console.log('err',err);
})
},[])

custom hooks return value doesn't change in Component

My custom hook fetches data asynchronously. When it is used in a component, returned value doesn't get updated. It keeps showing default value. Does anybody know what is going on? Thank you!
import React, {useState, useEffect} from 'react'
import { getDoc, getDocs, Query, DocumentReference, deleteDoc} from 'firebase/firestore'
export const useFirestoreDocument = <T>(docRef: DocumentReference<T>) => {
const [value, setValue] = useState<T|undefined>(undefined)
const [isLoading, setIsLoading] = useState<boolean>(true)
const update = async () => {
const docSnap = await getDoc(docRef)
if (docSnap.exists()) {
const data = docSnap.data()
setValue(data)
}
setIsLoading(false)
}
useEffect(() => {
update()
}, [])
console.log(value, isLoading) // it can shows correct data after fetching
return {value, isLoading}
}
import { useParams } from 'react-router-dom'
const MyComponent = () => {
const {userId} = useParams()
const docRef = doc(db, 'users', userId!)
const {value, isLoading} = useFirestoreDocument(docRef)
console.log(value, isLoading) // keeps showing {undefined, true}.
return (
<div>
...
</div>
)
}
It looks like youe hook is only being executed once upon rendering, because it is missing the docRef as a dependency:
export const useFirestoreDocument = <T>(docRef: DocumentReference<T>) => {
const [value, setValue] = useState<T|undefined>(undefined)
const [isLoading, setIsLoading] = useState<boolean>(true)
useEffect(() => {
const update = async () => {
const docSnap = await getDoc(docRef)
if (docSnap.exists()) {
const data = docSnap.data()
setValue(data)
}
setIsLoading(false)
}
update()
}, [docRef])
console.log(value, isLoading) // it can shows correct data after fetching
return {value, isLoading}
}
In addition: put your update function definition inside the useEffect hook, if you do not need it anywhere else. Your linter will complaing about the exhaustive-deps rule otherwise.
The useEffect hook is missing a dependency on the docRef:
export const useFirestoreDocument = <T>(docRef: DocumentReference<T>) => {
const [value, setValue] = useState<T|undefined>(undefined);
const [isLoading, setIsLoading] = useState<boolean>(true);
useEffect(() => {
const update = async () => {
setIsLoading(true);
try {
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
const data = docSnap.data();
setValue(data);
}
} catch(error) {
// handle any errors, log, etc...
}
setIsLoading(false);
};
update();
}, [docRef]);
return { value, isLoading };
};
The render looping issue is because docRef is redeclared each render cycle in MyComponent. You should memoize this value so a stable reference is passed to the useFirestoreDocument hook.
const MyComponent = () => {
const {userId} = useParams();
const docRef = useMemo(() => doc(db, 'users', userId!), [userId]);
const {value, isLoading} = useFirestoreDocument(docRef);
console.log(value, isLoading);
return (
<div>
...
</div>
);
};

How to fetch and rerender the component

Please tell me how to fetch new data into the array using useState. Each time useEffect is using, the array is initialized empty again. I need to pass this array to the table so that when the values change, the table is rendered again
const AccountContainer = () => {
let [isLoaded, setIsLoaded] = useState(false);
let [page, setPage] = useState(0);
let [accData, setAccData] = useState([]);
useEffect(() => {loadData()}, [page]);
const loadData = async () => {
const response = await fetch(API_URL);
const data = await response.json();
data.content.map(acc => {
setAccData([...accData, acc])
});
setIsLoaded(true);
};
return (
<table data={accData} />
)
};
export default AccountContainer;
added log
[] AccountContainer.js:30
[] AccountContainer.js:30
[] AccountContainer.js:30
[] AccountContainer.js:30
[] AccountContainer.js:30
[] AccountContainer.js:30
https://codesandbox.io/embed/great-rubin-poywh?fontsize=14&hidenavigation=1&theme=dark
Thanks in advance
here is the solution in the sandbox
// AccountList.jsx
import React from "react";
const AccountList = props => (
<div>
{console.warn(props)}
{props.dataAcc.map(acc => (
<div>{acc.email}</div>
))}
)
</div>
);
export default AccountList;
App.jsx
import React, { useState, useEffect } from "react";
import AccountList from "./AccountList";
import "./styles.css";
const AccountContainer = () => {
let [isLoaded, setIsLoaded] = useState(false);
let [page, setPage] = useState(0);
let [accData, setAccData] = useState([]);
const API_URL = `https://reqres.in/api/users?page=1`;
useEffect(() => {
loadData();
}, [page]);
const loadData = async () => {
const response = await fetch(API_URL);
const data = await response.json();
setAccData([...accData, ...data.data]);
setIsLoaded(true);
};
const renderTable = () => {
if (isLoaded) {
return (
<div>
{console.warn(accData)}
<AccountList dataAcc={accData} />
</div>
);
} else if (!isLoaded) return "Loading";
};
return renderTable();
};
export default AccountContainer;

TypeError: Cannot destructure property 'isLoading' of 'Object(...)(...)' as it is undefined

I want to build a loading spinner while request API with React, I use context in React to fetch API and make a isLoading state in the context but when I call isLoading in App.js. It have an error TypeError: Cannot destructure property 'isLoading' of 'Object(...)(...)' as it is undefined.
the context.js
/* eslint-disable react/prop-types */
/* eslint-disable no-underscore-dangle */
import React, { useState, useEffect, createContext, useCallback } from 'react';
import moment from 'moment';
import { getResource } from '../api/resourceApi';
import { getProject } from '../api/projectApi';
import { getBooking, deleteBooking, updateBooking } from '../api/bookingApi';
import { HEIGHT_BOOKING } from '../containers/App/constant';
import { compareByDay, getNumberOfDay, isWeekend } from '../utils/Date';
const CalendarContext = createContext();
const CalendarProvider = props => {
const [isDragLoading, setIsDragLoading] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [persons, setPersons] = useState([]);
const [projects, setProjects] = useState([]);
const [search, setSearch] = useState('');
const [searchResult, setSearchResult] = useState([]);
const [bookings, setBookings] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [startDay, setStartDay] = useState(moment('2019-12-30', 'YYYY-MM-DD'));
const [endDay, setEndDay] = useState(moment('2020-02-03', 'YYYY-MM-DD'));
const [disabled, setDisabled] = useState(false);
const [isHoverWorking, setIsHoverWorking] = useState(true);
const [addBookingStatus, setAddBookingStatus] = useState(true);
const [content, setContent] = useState({
resource: [],
booking: undefined,
startDate: moment(),
endDate: moment(),
});
const [start, setStart] = useState(0);
const [end, setEnd] = useState(0);
const [selecting, setSelecting] = useState(false);
const [resourceStart, setResourceStart] = useState(0);
const [first, setFirst] = useState(false);
const [startCellDay, setStartCellDay] = useState(moment());
const [lastDate, setLastDate] = useState(0);
const [isHover, setIsHover] = useState(false);
const [formIsOpening, setFormIsOpening] = useState(false);
const [bookingId, setBookingId] = useState(null);
const contentGlobal = () => content;
const setContentGlobal = newContent => {
setContent(newContent);
};
const hoverObject = {
start,
end,
selecting,
resourceStart,
first,
startCellDay,
lastDate,
isHover,
formIsOpening,
isHoverWorking,
addBookingStatus,
};
const onDisabled = () => {
setDisabled(!disabled);
};
const fetchResource = async () => {
setIsLoading(true);
const res = await getResource();
const result = res.data.resources;
const personsFilter = result.map(resource => {
const person = {
_id: resource._id,
name: `${resource.name.first} ${resource.name.last}`,
avatar: resource.avatar,
};
return person;
});
setPersons(personsFilter);
setSearchResult(personsFilter);
setIsLoading(false);
};
const fetchProject = async () => {
setIsLoading(true);
const res = await getProject();
const result = res.data.projects;
setProjects(result);
setIsLoading(false);
};
const fetchBooking = useCallback(async () => {
setIsLoading(true);
const res = await getBooking(startDay, endDay);
const result = res.data.bookings;
const bookingsConvert = result.map(booking => {
const schedule = {
...booking,
project: booking.project,
startDay: moment(booking.startDay),
endDay: moment(booking.endDay),
};
return schedule;
});
setBookings([...bookingsConvert]);
setIsLoading(false);
}, [startDay, endDay]);
const removeBooking = async id => {
const newBookings = bookings.filter(booking => booking._id !== id);
await deleteBooking(id);
setBookings([...newBookings]);
};
const handleSetBookings = (booking, onAdd = true) => {
if (onAdd) {
setBookings([...bookings, booking]);
} else {
const filterBooking = bookings.filter(e => e._id !== booking._id);
setBookings([...filterBooking, booking]);
}
};
const updateSearch = event => {
setSearch(event.target.value.toLowerCase());
};
function getBookingWithResource(date, indexResource) {
const bookingsWithResource = bookings
.filter(booking => {
const isBookingBelongResource =
booking.startDay.isSame(date, 'day') &&
booking.resourceId === searchResult[indexResource]._id;
return isBookingBelongResource;
})
.sort(
// eslint-disable-next-line no-shadow
(first, second) => compareByDay(second.endDay, first.endDay),
);
return bookingsWithResource;
}
useEffect(() => {
fetchResource();
return () => {};
}, []);
useEffect(() => {
fetchBooking();
return () => {};
}, [fetchBooking]);
useEffect(() => {
fetchProject();
return () => {};
}, []);
useEffect(() => {
const filteredResults = persons.filter(
item => item.name.toLowerCase().indexOf(search) !== -1,
);
setSearchResult(filteredResults);
}, [search, persons]);
return (
<CalendarContext.Provider
value={{
persons,
projects,
search,
searchResult,
updateSearch,
bookings,
setBookings,
fetchBooking,
handleSetBookings,
getMaxTotalOverlapBooking,
getBookingWithResource,
getMarginTopBooking,
isModalOpen,
handleCloseModal,
setStartDay,
setEndDay,
startDay,
endDay,
disabled,
onDisabled,
removeBooking,
setBegin,
updateOnDidDragBooking,
contentGlobal,
setContentGlobal,
start,
setStart,
end,
setEnd,
selecting,
setSelecting,
resourceStart,
setResourceStart,
first,
setFirst,
startCellDay,
setStartCellDay,
lastDate,
setLastDate,
isHover,
setIsHover,
addBookingStatus,
setAddBookingStatus,
formIsOpening,
hoverObject,
hoverSetObject,
isDragLoading,
setIsDragLoading,
bookingId,
isLoading,
}}
>
{props.children}
</CalendarContext.Provider>
);
};
export { CalendarProvider, CalendarContext };
App.js
import './App.css';
import './containers/Header/Header.css';
import React, { useContext, useEffect, useState } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import { theme } from './containers/common/AppStyle';
import Header from './components/Header';
import Dashboard from './containers/DashboardPage';
import { CalendarContext } from './context/Calendar';
const App = () => {
const context = CalendarContext;
const { isLoading } = useContext(context);
console.log(isLoading);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(false);
}, []);
if (loading) return null;
return (
<ThemeProvider theme={theme}>
<Router>
<Header />
<Switch>
<Route path="/dashboard" component={Dashboard} />
</Switch>
</Router>
</ThemeProvider>
);
};
export default App;
change:
value={{
isLoading,
}}
with
value={isLoading}

Resources