How to get the user city location in react native? earlier I was developing an app for android in using expo but due to some reasons, I rebuilt it in react native cli so how can I do the same in react native cli? i want to get user city name and then send that city name to backend i provide you my expo code how can i function this same in react native cli?
const [userdata, setUserdata] = useState(null);
const [location, setLocation] = useState(null);
const [errorMsg, setErrorMsg] = useState(null);
const [city, setCity] = useState(null);
useEffect(() => {
getUserData();
getLocation();
}, []);
const getUserData = useCallback(async () => {
try {
const userDataString = await AsyncStorage.getItem('user');
const userData = JSON.parse(userDataString);
setUserdata(userData);
} catch (err) {
alert(err);
}
}, []);
const getLocation = useCallback(async () => {
try {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
}
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
let city = await Location.reverseGeocodeAsync(location.coords);
setCity(city[0].city);
} catch (err) {
console.error(err);
}
}, []);
const sendCity = useCallback(async () => {
try {
const response = await fetch('https://backnedurl.com/GetCity', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
city: city,
username: userdata.user.username
}),
});
const data = await response.json();
console.log('Success:', data);
} catch (err) {
console.error('Error:', err);
}
}, [userdata, city]);
useEffect(() => {
if (userdata && city) {
sendCity();
}
}, [userdata, city, sendCity]);
AsyncStorage.getAllKeys()
.then((keys) => {
keys.forEach((key) => {
AsyncStorage.getItem(key)
.then((value) => {
console.log(`${key}: ${value}`);
})
.catch((error) => {
console.log(`Error retrieving data for key ${key}: ${error}`);
});
});
})
.catch((error) => {
console.log(`Error retrieving keys: ${error}`);
});
You can use react-native-get-location package to get latitude and longitude of the user. Then you can get city name using openstreetmap by sending lat and long.
Related
When I create an item and click save, I would like when I return to the page it automatically updates with what I just created. So that my useEffect detects the changes that have just arrived at the level of the GET request.
But I tried everything, I tried to put the variable garden in the array of useEffect but it makes an infinite loop of GET request, I also tried to put setGarden it does not make an infinite loop but it does not update automatically, I have to reload the page...
Here is the code :
const [garden, setGarden] = useState([]);
const [plot, setPlot] = useState([]);
const [loading, setLoading] = useState(false);
const navigation = useNavigation();
const gardenData = async () => {
setLoading(true);
const user = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(user);
try {
const response = await axios.get(
`http://127.0.0.1/api/garden?user=${parsedUserData.user.id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (response.status === 200) {
navigation.navigate('LogScreen');
setGarden(response.data);
setLoading(false);
try {
const plotResponse = await axios.get(
`http://127.0.0.1/api/plots?garden=${response.data[0].id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (plotResponse.status === 200) {
setPlot(plotResponse.data);
}
} catch (e) {
alert(e);
}
}
} catch (e) {
console.log('Erreur ' + e);
setLoading(false);
}
};
useEffect(() => {
gardenData();
}, []);
Thanks for the help !
You can just simply use an indication to make sure the gardenData function in ran once. Either you can initialize one of your state or even you can use a complete new state This is only run the code once.
const [garden, setGarden] = useState([]);
const [plot, setPlot] = useState([]);
const [loading, setLoading] = useState(false);
const [FirstRun, setFirstRun] = useState(true);
const navigation = useNavigation();
const gardenData = async () => {
if(!FirstRun) return;
setFirstRun(false);
setLoading(true);
const user = await AsyncStorage.getItem('user');
const parsedUserData = JSON.parse(user);
try {
const response = await axios.get(
`http://127.0.0.1/api/garden?user=${parsedUserData.user.id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (response.status === 200) {
navigation.navigate('LogScreen');
setGarden(response.data);
setLoading(false);
try {
const plotResponse = await axios.get(
`http://127.0.0.1/api/plots?garden=${response.data[0].id}`,
{
headers: {
Authorization: `Token ${parsedUserData.token}`,
},
},
);
if (plotResponse.status === 200) {
setPlot(plotResponse.data);
}
} catch (e) {
alert(e);
}
}
} catch (e) {
console.log('Erreur ' + e);
setLoading(false);
}
};
useEffect(() => {
if(FirstRun)
{
gardenData();
}
// your code here
}, [garden]);
my custom hooks :
import { useContext, useState } from "react";
import { AppContext } from "../context/app.context";
const usePostAxios = (url) => {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const { setUrl, token } = useContext(AppContext);
const postData = async (data) => {
try {
setIsLoading(true);
axios.defaults.headers.common["X-Authreq"] = token;
await axios
.post(`${setUrl}/${url}`, data)
.then(({ data }) => {
setData(data);
})
.catch((err) => {
setError(err.response || err.request);
});
setIsLoading(false);
} catch (err) {
console.log(err);
}
};
return [isLoading, postData, data, error];
};
export { usePostAxios };
for posting data :
const [isPosting, postFun, res, err] = usePostAxios("/apidet/EmpLog");
const handleSubmit = async (val) => {
await postFun({
UserName: val.email,
password: val.pass,
});
if (res) {
const { Apd, Apt } = res.ResponseData;
dispatch({ type: "APP-LOGIN", token: `${Apd}:${Apt}` });
setIsError(false);
navigate("Home");
return;
} else {
setIsError(true);
return;
}
};
then why my code is getting in else block and getting error but when i press submit button again the code run successfully and my login process success
so why is my code not running on first try ?
am i doing something stupid ?
Well, wrote in this way, basically, when this this code is excecuted
if(res) {
// Something to do with result
}
the variable res has null as value, initially.
You should check for changes in res with useEffect instead, like:
useEffect(()=> {
if(res) {
// Something to do with result
}
}, [res])
I'm making a get request to an API in a useEffect(). When I navigate to the page from the homepage it loads fine, but as soon as i refresh the page http://localhost:3000/coins/coin I get a Unhandled Runtime Error: Error: Network Error.
export async function getServerSideProps({ query }) {
const id = query;
return {
props: { data: id },
};
}
function index({ data }) {
const coinURL = data.id; // bitcoin
const apiEndpoint = `https://api.coingecko.com/api/v3/coins/${coinURL}`;
const [currentUser, setCurrentUser] = useState();
const [coinData, setCoinData] = useState([]);
useEffect(() => {
const getData = async () => {
const res = await axios.get(apiEndpoint);
const { data } = res;
setCoinData(data);
};
const getCurrentUser = async () => {
const res = await axios.get(
`http://localhost:5000/api/users/${session?.id}`
);
const { data } = res;
setCurrentUser(data);
};
getData();
getCurrentUser();
}, [coinData, currentUser]);
}
Why does this happen?
I'm recommending to do something like this:
const getData = async () => {
try {
const res = await axios.get(apiEndpoint);
const { data } = res;
setCoinData(data);
} catch(err) {
console.log(err)
}
};
const getCurrentUser = async () => {
try {
const res = await axios.get(
`http://localhost:5000/api/users/${session?.id}`
);
const { data } = res;
setCurrentUser(data);
} catch(err) {
console.log(err)
}
};
useEffect(() => {
getData();
getCurrentUser();
}, [coinData, currentUser]);
if you do so, you will be able to view the exact error and fix it.
The question could be seen as similar to this one but is not working really the same way as that one is checking for a function to be called while im looking for a state to change.
The code i have is this one (headers and body are not really important in this case):
const useGetToken = () => {
const [token, setToken] = useState();
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
const fetchToken = useCallback(() => {
setLoading(true);
fetch('http://localhost.something', {
headers,
body,
})
.then((response) => {
response.json();
})
.then((response) => {
setToken(response.access_token);
})
.catch((e) => {
setError(e);
})
.finally(() => {
setLoading(false);
});
}, []);
return { fetchToken, token, error, loading };
};
what I am trying to find is a way to test that the output I have is the correct one in case of success and in case of error.
Seems like I can mock until the first .then but then i dont know how to mock the second one.
import { renderHook, act } from '#testing-library/react-hooks';
describe('useGetToken', () => {
it('should fetch and return a token', () => {
global.fetch = jest.fn().mockImplementation(() =>
Promise.resolve({
json: () => ({ access_token: 'aToken' }),
}),
);
const { result } = renderHook(() => useGetToken());
// also how to check for the fetchToken function to equal to itself i dont know how to do
// or maybe i can check if it is just a function
expect(result.current).toEqual({ token: 'aToken', loading: false, error: false });
});
});
managed a way to fix it changing with async await and the correct act.
also changed the double .then in the file to this
.then((response) => {
const parsedResponse = response.json();
setToken(parsedResponse.access_token);
})
cause i didnt need two
import { renderHook, act } from '#testing-library/react-hooks';
import useGetToken from '../useGetVfsToken';
describe('useGetToken', () => {
it('should fetch when fetchToken is called', async () => {
global.fetch = jest.fn().mockImplementation(() =>
Promise.resolve({
json: () => ({ access_token: 'aToken123' }),
}),
);
const { result } = renderHook(() => useGetToken());
expect(window.fetch).not.toHaveBeenCalled();
await act(async () => {
result.current.fetchToken();
});
expect(window.fetch).toHaveBeenCalledTimes(1);
expect(result.current.token).toEqual('aToken123');
expect(result.current.loading).toEqual(false);
expect(result.current.error).toBeUndefined();
});
it('should have an error', async () => {
const error = 'an error text';
global.fetch = jest.fn().mockImplementation(() => Promise.reject(error));
const { result } = renderHook(() => useGetToken());
await act(async () => {
result.current.fetchToken();
});
expect(result.current.error).toEqual(error);
expect(result.current.loading).toEqual(false);
});
});
I write following code to authenticate with react but have one problem. after user logged in, set token in local storage and redirect the user to the dashboard and in this page check token from local storage and if not exist redirect the user to the login page and my problem is here!! when come in dashboard page can't get token because return null to me but if refresh the page return token!!
In fact, I'm can't get token after set that.
My codes is:
export const userLogin = (data) => {
return (dispatch) => {
return axios.post(API.USER_LOGIN,data).then((response) => {
dispatch(loginSuccess());
setToken(response.data.token);
dispatch(setUserToken(response.data.token))
}).then(() => {
dispatch(fetchUser());
}).catch((error) => {
dispatch(setFormErrors({errors: error.response.data}));
})
}
};
export const fetchUser = () => {
return (dispatch, getState) => {
dispatch(authLoading(true));
const { userToken } = getState().auth;
return axios.post(API.CURRENT_USER, null, {
headers: { authorization: `Bearer ${userToken}` },
}).then((response) => {
const { id, name, username, email } = response.data.user;
dispatch(setCurrentUser({current_user: { id, name, username, email }}));
dispatch(authLoading(false));
}).catch((error) => {
if(error.response.status) {
dispatch(logout());
}
});
};
};
export const checkToken = () => {
return async (dispatch, getState) => {
const token = await getToken();
const { userToken } = getState().auth;
if (token || userToken) {
dispatch(loginSuccess());
dispatch(fetchUser());
}
};
}
export const setToken = token => localStorage.setItem('token', token);
export const getToken = () => localStorage.getItem('token');
export const clearToken = () => localStorage.removeItem('token');