why is axios get + post request timing out after 5 button requests? - reactjs

I'm attempting to get and post data using axios from server (express, axios, react native) and after 5x pressing the button it disconnects from server.
please see web example - console log
Is there a default timeout after 5 or 6 request calls - iOS is 3 calls before disconnect - android 5 calls before disconnect - web 6 calls - it varies across platforms. Logs perfectly fine until disconnect.
//client:
const [i, setI] = useState(0)
const [connecter, setConnecter] = useState()
const mainURL = "http://192.168.0.26:8080/usr"
const datas = {
val : "counter!" + " " + i
}
const func = () => {
setI(i + 1)
axios({
method: 'post',
url: mainURL + "/play",
data: JSON.stringify(datas),
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
maxContentLength: Infinity,
maxBodyLength: Infinity
})
.then(() => {
console.log("sent!")
})
.catch(err => console.log(err))
};
const red = axios.get(mainURL + "/connect",
{headers:{"Content-Type": "application/json"}})
.then((res) => {
setConnecter(res.status)
}).catch((err) => setConnecter(err))
useEffect(() => {
}, [red])
//server
router.get("/connect", (req, res) => {
res.send("Server Connected")
})
router.post("/play", async(req, res) => {
const resser = await req.body
console.log(resser)
})

You can try using this code:
import * as React from 'react';
import {useEffect, useState} from 'react';
import { Button, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import * as axios from "axios";
export default function App() {
const mainURL = "http://192.168.0.26:8080/usr";
const [counter, setCounter] = useState(0);
const [connecter, setConnecter] = useState(null);
const [data, setData] = useState({
val: `counter! ${counter}`
});
useEffect(() => {
setData({
val: `counter! ${counter}`
});
}, [counter]);
const callApi = async () => {
try {
const connectRes = await axios.post('https://reqres.in/api/users', JSON.stringify(data), { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }});
console.log(connectRes);
setConnecter(connectRes);
const result = await axios.get('https://reqres.in/api/products/3', { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }});
setCounter(prev => prev + 1);
console.log(counter);
console.log(result);
} catch (e) {
console.log('error', e);
}
}
return (
<View style={styles.container}>
<Button title="test" onPress={() => callApi()} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});
you can check this working example from here.

Related

converting custom react function to async

I made this custom hook.
import axios from "axios";
import Cookies from "js-cookie";
import React from "react";
const useGetConferList= () => {
let token = JSON.parse(localStorage.getItem("AuthToken"));
const Idperson = JSON.parse(Cookies.get("user")).IdPerson;
const [response, setResponse] = React.useState();
const fetchConfer= (datePrensence, idInsurance, timePrensence) => {
axios({
method: "post",
url: `${process.env.REACT_APP_API_URL_API_GET_ERJASERVICE_LIST}`,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
data: JSON.stringify({
datePrensence,
idInsurance,
Idperson,
searchfield: "",
timePrensence: parseInt(timePrensence) * 60,
}),
})
.then((r) => {
setResponse(r.data.Data);
})
.catch(() => alert("NetworkError"));
};
return { fetchConfer, response };
};
export default useGetConferList;
as you can see I export the fetchConfer function. but I want to make it async. for example, calling the function and then doing something else like this:
fetchConfer(Date, Time, Id).then((r) => {
if (search !== "") {
window.sessionStorage.setItem(
"searchList",
JSON.stringify(
r.data
)
);
}
});
as you can see in non async situation, I can't use then.
You can try this
const fetchConfer = async (datePrensence, idInsurance, timePrensence) => {
try {
const response = await axios({
method: "post",
url: `${process.env.REACT_APP_API_URL_API_GET_ERJASERVICE_LIST}`,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
data: JSON.stringify({
datePrensence,
idInsurance,
Idperson,
searchfield: "",
timePrensence: parseInt(timePrensence) * 60,
}),
})
setResponse(response.data.Data);
// need to return data
return response.data.Data
} catch(error) {
alert("NetworkError")
}
};
use the function in another async function
const someAsyncFunc = async () => {
// try catch
const r = fetchConfer(Date, Time, Id)
if (search !== "") {
window.sessionStorage.setItem(
"searchList",
JSON.stringify(
r.data
)
);
}
...
or use it how you are currently using it
Hope it helps

Why I need to refresh manually to fetch data api in react?

I make react app using react router v5, and axios as api instance. I fetch the data in AppRouter file.
Here is my approuter.tsx
const AppRouter = () => {
const dispatch = useAppDispatch();
const token = useAppSelector((state) => state.user.token);
const getUser = useCallback(async () => {
const { data } = await Services.getUser();
dispatch(userAction.setUser(data));
}, [dispatch]);
useEffect(() => {
const localStorage = new LocalStorageWorker();
const storageToken = localStorage.get('token');
dispatch(userAction.setToken(storageToken));
}, [dispatch]);
useEffect(() => {
if (token) {
getUser();
console.log('Worked');
}
}, [token, getUser]);
return (
...
)
}
Actually the function work properly, but I need to refresh the page manually to run these functions. How can I make the function run without refreshing the page?
Update:
The problem is because my axios create instance. I should use interceptors to keep the data fetching in useEffect.
My instance looks like this:
(before update)
const token = localStorage.get('token');
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.defaults.headers.common.Authorization = `Bearer ${token}`;
return instance;
};
(after update)
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.interceptors.request.use(
(config) => {
const token = window.localStorage.getItem('token');
if (token) {
return {
...config,
headers: { Authorization: `Bearer ${token}` },
};
}
return null;
},
(err) => Promise.reject(err)
);
return instance;
};
And now the data fetching is work properly. Thank you

React Typescript file getting converted to a video format

I have a small React project that I am in the process of converting to typescript. I am currently trying to convert a Context file into Typescript. For reference, here is the original JS code:
import { createContext, useCallback, useState } from "react";
import netlifyIdentity from 'netlify-identity-widget';
export const AppContext = createContext()
export function useAppContext() {
const [user, setUser] = useState(netlifyIdentity.currentUser())
const genericAuthedFetch = useCallback((
endpoint,
method = 'GET',
body = null,
) => {
if (!(!!user && !!user.token && !!user.token.access_token)) {
return Promise.reject('no user token found');
}
const options = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method,
body: body === null ? null : JSON.stringify(body),
};
return fetch(endpoint, options);
}, [user]);
const getStockData = (ticker, target) => {
var url = new URL('.netlify/functions/get-price', window.location.origin)
url.search = new URLSearchParams({ ticker, target }).toString()
return genericAuthedFetch(url);
}
const createAccount = (params) => {
return genericAuthedFetch(
new URL('.netlify/functions/create-account', window.location.origin),
'POST',
params);
}
const listAccounts = (date) => {
var url = new URL('.netlify/functions/list-accounts', window.location.origin);
url.search = new URLSearchParams({ timestamp: date.getTime() }).toString()
return genericAuthedFetch(url);
}
const loginUser = useCallback((user) => {
fetch(
new URL('.netlify/functions/make-user', window.location.origin),
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method: 'POST'
}).then((_) =>
setUser(user))
}, [setUser])
const logoutUser = useCallback((user) => setUser(null), [setUser])
netlifyIdentity.on("login", loginUser);
netlifyIdentity.on("logout", logoutUser);
const loginPopup = () => netlifyIdentity.open('login')
const signupPopup = () => netlifyIdentity.open('signup')
const logout = () => netlifyIdentity.logout();
return {
user,
logout,
loginPopup,
signupPopup,
getStockData,
listAccounts,
createAccount
}
}
And here is the associated TS code
import React, { createContext, useCallback, useState } from "react";
import netlifyIdentity, { User } from 'netlify-identity-widget';
import { CreateAccountRequest, CreateAccountResponse, GetPriceRequest, GetPriceResponse, ListAccountsRequest, ListAccountsResponse } from "../types/types";
export interface Context {
user?: User
logout: () => void
loginPopup: () => void
signupPopup: () => void
getStockData: (req: GetPriceRequest) => Promise<GetPriceResponse>
listAccounts:(req: ListAccountsRequest) => Promise<ListAccountsResponse>
createAccount: (req: CreateAccountRequest) => Promise<CreateAccountResponse>
}
export const AppContext: React.Context<Context> = createContext({} as Context)
export function useAppContext() {
const [user, setUser] = useState(netlifyIdentity.currentUser())
const genericAuthedFetch = useCallback((
endpoint: URL,
method = 'GET',
body: any = null,
) => {
if (!user?.token?.access_token) {
return Promise.reject('no user token found');
}
const options = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method,
body: body === null ? null : JSON.stringify(body),
};
return fetch(endpoint, options);
}, [user]);
const getStockData = (req: GetPriceRequest) => {
var url = new URL('.netlify/functions/get-price', window.location.origin)
url.search = new URLSearchParams({ ticker: req.ticker, target: req.target }).toString()
return genericAuthedFetch(url);
}
const createAccount = (req: CreateAccountRequest) => {
return genericAuthedFetch(
new URL('.netlify/functions/create-account', window.location.origin),
'POST',
req);
}
const listAccounts = (req: ListAccountsRequest) => {
var url = new URL('.netlify/functions/list-accounts', window.location.origin);
url.search = new URLSearchParams({ timestamp: req.timestamp.toString() }).toString()
return genericAuthedFetch(url);
}
const loginUser = useCallback((user: User) => {
fetch(
new URL('.netlify/functions/make-user', window.location.origin),
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user?.token?.access_token,
},
method: 'POST'
}).then((_) =>
setUser(user))
}, [setUser])
const logoutUser = useCallback(() => setUser(null), [setUser])
netlifyIdentity.on("login", loginUser);
netlifyIdentity.on("logout", logoutUser);
const loginPopup = () => netlifyIdentity.open('login')
const signupPopup = () => netlifyIdentity.open('signup')
const logout = () => netlifyIdentity.logout();
return {
user,
logout,
loginPopup,
signupPopup,
getStockData,
listAccounts,
createAccount
}
}
The problem I am encountering is that when I use the dev server or create a production build using npm run build, the typescript version of this file becomes mangled in a strange way.
Specifically, the contents of the typescript file becomes
module.exports = "data:video/MP2T;base64,<base64 encoded typescript file>"
//////////////////
// WEBPACK FOOTER
// ./src/AppContext.ts
// module id = 115
// module chunks = 0
I have done some research, and the only thing I have found is that .ts is also the extension of MPEG transport stream, so that could partially explain it. Something thinks my typescript code is a video file, but I have no idea what is doing that or why.
How do I get this to compile correctly?

React Redux components with REST Endpoints and reusable components

I am working on a React-Redux (with hooks) project, where I have a baseURL with different endpoints. For example
baseURL = "https://jsonplaceholder.typicode.com"
endpoints = "/posts", "/comments", "/albums"
I have 2 questions:
Where to keep the endpoint in the react (comments) component (for example: "/comments")
How to reuse the code for other components like posts and albums because the accessToken code and headers are same for all of them.
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50,
};
return fetch(baseURL, {
credentials: "include",
method: "post",
body: JSON.stringify(bodyParameters),
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache",
},
My redux action looks like this
export const readList = () => {
return (dispatch) => {
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50,
};
return fetch(baseURL, {
credentials: "include",
method: "post",
body: JSON.stringify(bodyParameters),
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache",
},
})
.then((response) => {
return response.json();
})
.then((data) =>
dispatch(
{
type: READ_LIST,
payload: data,
},
console.log("Actions: ", data)
)
)
.catch((error) => {
console.log(error.response);
throw error;
});
};
};
and the react component looks like this
import "./styles.css";
import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { readList } from "./redux/actionCreators";
import { FormattedMessage } from "react-intl";
import { DataGrid } from "#material-ui/data-grid";
export default function App() {
const dispatch = useDispatch();
const historyList = useSelector(
(state) => state.reducers.commentsData.data || []
);
useEffect(() => {
dispatch(readList());
}, [dispatch]);
let rows = historyList.map((obj, index) => {
return (rows = {
id: index,
"User ID": obj.userId,
Title: obj.title,
Body: obj.body
});
});
const columns = [
{
field: "User ID",
flex: 1,
renderHeader: () => <FormattedMessage id={"userId"} />
},
{
field: "Title",
flex: 1,
value: "dropdown",
renderHeader: () => <FormattedMessage id={"title"} />
},
{
field: "Body",
flex: 1,
type: "date",
renderHeader: () => <FormattedMessage id={"body"} />
}
];
return (
<div className={"uhes-pageWrapper"}>
<h1 className="uhes-pageHeader">
<FormattedMessage id="History" />
</h1>
<div style={{ height: "90%", width: "100%" }}>
<DataGrid
pageSize={50}
rowsPerPageOptions={[50, 100, 150]}
rows={rows}
columns={columns}
/>
</div>
</div>
);
}
Thank you!
The ideas to reuse api configs, includes baseURL, accesstoken,... somethings like this
You will have a service called apiService: where you manage your fetch configs like headers, and you can also add your token in there. apiService will return REST functions: POST/PUT/GET/DELETE/PATCH with available header configurations
Example:
const customFetch = (path, options) => {
const accessToken = localStorage.getItem("accessToken");
Cookies.set("XSRF-TOKEN", Cookies.get("XSRF-TOKEN"));
var bodyParameters = {
page: 1,
pageSize: 50
};
return fetch(`${baseURL}/${path}`, {
credentials: "include",
headers: {
Authorization: `JWT ${accessToken}`,
"X-XSRF-TOKEN": Cookies.get("XSRF-TOKEN"),
"cache-control": "no-cache",
pragma: "no-cache"
},
...options
});
};
const post = (path, bodyParameters) =>
customFetch(path, {
method: "POST",
body: JSON.stringify(bodyParameters)
});
const get = (path, queries) =>
customFetch(queries ? `${path}/${qs.stringify(queries)}` : path, {
method: "GET"
});
const put = (path, bodyParameters) =>
customFetch(path, {
method: "PUT"
body: JSON.stringify(bodyParameters)
});
const delete = (path, id) =>
customFetch(`${path}/${id}`, {
method: "DELETE"
});
After that you can custom your readList with dynamic endpoint like this
const readList = (resource) => apiService.get(resource)
readList('/posts');
readList('/comments');
readList('/albums');

React Follow Function activates on page load

I am trying to implement a follow/unfollow function in a react rails-api web application. Currently the follow and unfollow post/delete just fine when I click the follow/unfollow button.
However, whenever a user visits another users page it will follow/unfollow when the page loads without clicking the follow/unfollow button. I do not understand why this is happening since I have, for my post/delete, the useEffect second param set to go off when the state for my follow/unfollow changes.
Please help me figure out why this is happening and how to prevent this. Let me know if more information is needed.
import React, {useState, useEffect} from 'react'
import {Link, useParams} from 'react-router-dom'
import decode from 'jwt-decode'
function NotUserPage() {
const {id} = useParams()
const [user, setUser] = useState({})
const loggedUser = decode(localStorage.getItem("token"))
const username = loggedUser.username
const userId = loggedUser.user_id
const [followUnFollow, setFollowUnFollow] = useState("true")
const toggleFollowUnFollow = () => {
setFollowUnFollow(!followUnFollow)
}
const fetchUserData = () => {
fetch(`http://localhost:3000/users/${id}`)
.then(res => res.json())
.then(data => setUser(data))
}
useEffect(() => {
fetchUserData()
}, [])
const unFollow = () => {
fetch(`http://localhost:3000/users/${id}/unfollow`, {
method: "POST",
body: JSON.stringify({
follower_id: userId,
followee_id: id
}),
headers: {
"Content-type": "application/json",
"Authorization": `bearer ${localStorage.getItem("token")}`,
},
})
.then(res => res.json())
.then(data => console.log(data))
}
useEffect(() => {
unFollow()
}, [followUnFollow])
const handleFollow = () => {
fetch(`http://localhost:3000/users/${id}/follow`, {
method: "POST",
body: JSON.stringify({
follower_id: userId,
followee_id: id
}),
headers: {
"Content-type": "application/json",
"Authorization": `bearer ${localStorage.getItem("token")}`,
},
})
.then(res => res.json())
.then(data => console.log(data))
}
useEffect(() => {
handleFollow()
}, [followUnFollow])
const fButton = () => {
toggleFollowUnFollow() ? handleFollow() : unFollow()
}
return (
<div>
{user.username}
<button onClick={fButton}>follow</button>
</div>
)
}
export default NotUserPage
import React, {useState, useEffect} from 'react'
import {Link, useParams} from 'react-router-dom'
import decode from 'jwt-decode'
function NotUserPage() {
const {id} = useParams()
const [user, setUser] = useState({})
const loggedUser = decode(localStorage.getItem("token"))
const username = loggedUser.username
const userId = loggedUser.user_id
const [following, setFollowing] = useState(false)
const fetchUserData = () => {
fetch(`http://localhost:3000/users/${id}`)
.then(res => res.json())
.then(data => setUser(data))
}
useEffect(() => {
fetchUserData()
}, [])
const unFollow = () => {
fetch(`http://localhost:3000/users/${id}/unfollow`, {
method: "POST",
body: JSON.stringify({
follower_id: userId,
followee_id: id
}),
headers: {
"Content-type": "application/json",
"Authorization": `bearer ${localStorage.getItem("token")}`,
},
})
.then(res => res.json())
.then(data => console.log(data))
.then(() => setFollowing(false))
}
const handleFollow = () => {
fetch(`http://localhost:3000/users/${id}/follow`, {
method: "POST",
body: JSON.stringify({
follower_id: userId,
followee_id: id
}),
headers: {
"Content-type": "application/json",
"Authorization": `bearer ${localStorage.getItem("token")}`,
},
})
.then(res => res.json())
.then(data => console.log(data))
.then(() => setFollowing(true))
}
const fButton = () => following ? unFollow() : handleFollow();
return (
<div>
{user.username}
<button onClick={fButton}>follow</button>
</div>
)
}
export default NotUserPage

Resources