I am trying to consume an API in my react but I can't seem to load the response on my react frontend.
when I check the network on my browser, I can see the response, but it does not display on the web page.
my code is below can't seem to know what's wrong.
import { useState, useEffect } from "react";
import axios from "axios";
import "./PrivateScreen.css";
const PrivateScreen = ({ history }) => {
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState(null);
const url = "https://jsonplaceholder.typicode.com/users";
useEffect(() => {
if(!localStorage.getItem("authToken")) {
history.push("/login")
}
const fetchPrivateDate = async () => {
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("authToken")}`,
},
};
try {
await axios.get(url, config)
.then(res => {
setPrivateData(res.data);
});
} catch (error) {
localStorage.removeItem("authToken");
setError("You are not authorized. Please login");
}
};
fetchPrivateDate();
}, [history]);
const logoutHandler = () => {
localStorage.removeItem("authToken");
history.push("/login");
};
return error ? (
<span className="error-message">{error}</span>
) : (
<>
<div style={{ background: "green", color: "white" }}>
{privateData.name}
</div>
<div><p>hello from this side</p></div>
<button onClick={logoutHandler}>Log Out</button>
</>
);
};
export default PrivateScreen;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
First you must change instead of
const [privateData, setPrivateData] = useState(null);
const [privateData, setPrivateData] = useState([]);
when calling the array data we want initialize an empty array
Then second when we are showing array data with help map method we want to call like this,Let me know issue is fixed
{privateData.map((privateDatas) => (
<div style={{ background: "green", color: "white" }}>
{privateDatas.name}
</div>
))}
Related
I have a component (ownPrescriptionsPanel) inside which I'm rendering another component (PrescriptionsList). Inside the parent component, I have a useEffect hook to fetch data using Axios for the child component (PrescriptionsList). The problem is no matter what I try, the PrescriptionsList is always empty and only gets populated when I refresh. I have three child components (all are PrescriptionsList components) but I've shown only one in the below code.
import React, { useEffect, useState } from "react";
import Axios from "axios";
import { PrescriptionsList } from "../../components/prescriptionsList/prescriptionsList";
import "./ownPrescriptionsPanelStyles.css";
export const OwnPrescriptionsPanel = () => {
const [pastPrescriptions, setPastPrescriptions] = useState([]);
const [openPrescriptions, setOpenPrescriptions] = useState([]);
const [readyPrescriptions, setReadyPrescriptions] = useState([]);
const [isBusy1, setIsBusy1] = useState(true);
useEffect(() => {
Axios.post(
"http://localhost:3001/getpatientprescriptions",
{
id: sessionStorage.getItem("id"),
},
{
headers: {
"Content-Type": "application/json",
},
}
).then((response) => {
console.log("getpatientprescriptions", response.data);
var resArr = []; //getting rid of the duplicates
response.data.filter(function (item) {
var i = resArr.findIndex(
(x) => x.prescriptionId === item.prescriptionId
);
if (i <= -1) {
resArr.push(item);
}
return null;
});
setPastPrescriptions(resArr);
setIsBusy1(false);
});
}, []);
if (isBusy1) {
return <div>loading</div>;
}
return (
<>
<PrescriptionsList
pastPrescriptions={pastPrescriptions}
heading="All prescriptions"
viewOnly={true}
prescriptionStatusOpen={false}
showPharmacy={false}
/>
</>
);
};
Edit: Given below is the code for PrescriptionList component
import React, { useState } from "react";
import Axios from "axios";
import DescriptionTwoToneIcon from "#mui/icons-material/DescriptionTwoTone";
import PresciptionModal from "../prescriptionModal/prescriptionModal";
import "./prescriptionsListStyles.css";
export const PrescriptionsList = ({
pastPrescriptions,
heading,
viewOnly,
showPharmacy,
}) => {
const [prescriptionDetails, setprescriptionDetails] = useState([]);
const [prescriptionDrugList, setPrescriptionDrugList] = useState([]);
const [open, setOpen] = useState(false);
const handleClose = () => {
console.log("close");
setOpen(false);
};
console.log("pastPrescriptions", pastPrescriptions);
const getPrescriptionDrugDetails = async (prescriptionId) => {
await Axios.post(
"http://localhost:3001/prescriptionDrugDetails",
{
prescriptionId: prescriptionId,
},
{
headers: {
"Content-Type": "application/json",
},
}
).then((response) => {
console.log("prescriptionDrugDetails", response.data);
setPrescriptionDrugList(response.data);
});
};
const handlePrescriptionClick = async (prescriptionDetails) => {
console.log("prescriptionDetails", prescriptionDetails);
setprescriptionDetails(prescriptionDetails);
await getPrescriptionDrugDetails(prescriptionDetails.prescriptionId);
setOpen(true);
};
const pastPrescriptionsList = pastPrescriptions.map((d) => (
<div
value={d}
onClick={() => handlePrescriptionClick(d)}
key={d.drugId}
className="prescriptionListItem"
>
<div style={{ width: "30px" }}>
<DescriptionTwoToneIcon fontSize="small" />
</div>
{d.prescriptionId}
</div>
));
const markPrescriptionComplete = async (d) => {
await Axios.post(
"http://localhost:3001/markcomplete",
{
prescriptionId: d.prescriptionDetails.prescriptionId,
pharmacyId: d.prescriptionDetails.pharmacyId,
},
{
headers: {
"Content-Type": "application/json",
},
}
);
console.log(
"prescriptionId, pharmacyId",
d.prescriptionDetails.prescriptionId,
d.prescriptionDetails.pharmacyId
);
window.location.reload(true);
};
return (
<div className="prescriptionsListContainer">
<div className="viewPrescriptionsLabel">{heading}</div>
<div className="prescriptionsContainer">{pastPrescriptionsList}</div>
{open && (
<PresciptionModal
open={open}
onClose={handleClose}
prescriptionDetails={prescriptionDetails}
prescriptionDrugList={prescriptionDrugList}
viewOnly={viewOnly}
// prescriptionStatusOpen={false}
markprescriptioncomplete={markPrescriptionComplete}
showPharmacy={showPharmacy}
/>
)}
</div>
);
};
I tried solution 1, solution 2 and the code shown above is using solution from geeksforgeeks. None seem to be working
I have already API responses and I want to show them in a table format.But it doesn't work. I took columns data from hostdatatablesource, and for rows, I called API in this page.
And I get this error:
react-dom.development.js:67 Warning: Failed prop type: Invalid prop rows of type object supplied to ForwardRef(DataGrid), expected array.
import "./datatable.scss";
import { DataGrid } from "#mui/x-data-grid";
import { userColumns } from "../../hostdatatablesource";
import { Link } from "react-router-dom";
import { useState,useEffect } from "react";
import useAxiosPrivate from "../../hooks/useAxiosPrivate";
const HOST_URL = '/organizers';
const Datatable = () => {
const [data, setData] = useState([]);
const axiosPrivate = useAxiosPrivate();
useEffect(() => {
let isMounted = true;
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await axiosPrivate.get(HOST_URL,
{
signal: controller.signal
});
isMounted && setData(response.data);
}
catch (err) {
if (err.response) {
// Not in the 200 response range
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
} else {
console.log(`Error: ${err.message}`);
}
}
}
fetchData();
return () =>{
isMounted = false;
controller.abort();
}
}, [])
const handleDelete = (id) => {
setData(data.filter((item) => item.id !== id));
};
const actionColumn = [
{
field: "action",
headerName: "Action",
width: 200,
renderCell: (params) => {
return (
<div className="cellAction">
<Link to="/host/Hostsingle" style={{ textDecoration: "none" }}>
<div className="viewButton">View</div>
</Link>
<div
className="deleteButton"
onClick={() => handleDelete(params.row.id)}
>
Delete
</div>
</div>
);
},
},
];
return (
<div className="datatable">
<div className="datatableTitle">
Add New Host
<Link to="/host/new" className="link">
Add Host
</Link>
</div>
<DataGrid
className="datagrid"
rows={data}
columns={userColumns.concat(actionColumn)}
pageSize={9}
rowsPerPageOptions={[9]}
checkboxSelection
/>
</div>
);
};
export default Datatable;
Your response.data must be an array. So, check if the setData(response.data) is an array or not. You can use console.log(response.data) to be sure about it.
I have a simple react app in which I am fetching the data using jsonplaceholder API and displaying the data with a delete button. I have a function deleteUser inside the User.js component. Now I want to make this deleteUser function a general function so I created a separate hook for it.
Now I want to pass arguments to that custom hook but I get the error
React Hooks must be called in a React function component or a custom
React Hook function react-hooks/rules-of-hooks
userDelete.js
import { useFetch } from "./useFetch";
export const useDelete = (userName) => {
const { data, setData} = useFetch();
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log(newData);
setData(newData)
};
useFetch.js
import { useState, useEffect } from "react";
export const useFetch = () => {
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const url = `https://jsonplaceholder.typicode.com/users`;
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const data = await response.json();
console.log(data);
setData(data);
setLoading(false);
return;
} catch (error) {
console.log("Error", error);
}
};
useEffect(() => {
fetchData();
}, []);
return { loading, data, setData };
};
User.js
import { useFetch } from "../Hooks/useFetch";
import { useDelete } from "../Hooks/useDelete";
const Users = () => {
const { loading, data, setData } = useFetch();
const deleteCallback = useDelete(data);
const deleteUser = (userName) => {
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log("newData", newData);
setData(newData);
};
return (
<>
<h1>Custom Hook Example</h1>
{loading && <h4>Fetching Data...</h4>}
{data.map((data, index) => (
<div
key={index}
style={{
border: "2px solid red",
width: "fit-content",
margin: "0 auto"
}}
>
<p>Name: {data.name}</p>
<article>Email: {data.email}</article>
{/* <button onClick={(e) => deleteUser(data.name, e)}>Delete</button> */}
<button onClick={() => useDelete(data.name)}>Delete</button>
</div>
))}
{data.length === 0 && (
<>
<p>No Items to Show</p>
</>
)}
</>
);
};
export default Users;
What am I doing wrong ?
I get this error when I try and call a function I have imported within my useEffect() hook in Dashboard.jsx. I am just trying to pull in data from database on the page load pretty much so that when user click button they can send off correct credentials to the api.
I am pulling it in from database for security reasons, so client id is not baked into the code.
I am pretty sure that I am getting this error maybe because the function is not inside a react component? although I am not 100% sure. And if that is the case I am not sure of the best way to restructure my code and get the desired output.
Code below.
mavenlinkCredentials.js
import { doc, getDoc } from "firebase/firestore";
import { useContext } from "react";
import { AppContext } from "../../context/context";
import { db } from "../../firebase";
const GetMavenlinkClientId = async () => {
const {setMavenlinkClientId} = useContext(AppContext)
const mavenlinkRef = doc(db, 'mavenlink', 'application_id');
const mavenlinkDocSnap = await getDoc(mavenlinkRef)
if(mavenlinkDocSnap.exists()){
console.log("mavenlink id: ", mavenlinkDocSnap.data());
console.log(mavenlinkDocSnap.data()['mavenlinkAccessToken'])
setMavenlinkClientId(mavenlinkDocSnap.data()['application_id'])
} else {
console.log("No doc");
}
}
export default GetMavenlinkClientId;
Dashboard.jsx
import React, { useContext, useEffect, useState } from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { useNavigate } from "react-router-dom";
import { query, collection, getDocs, where, setDoc, doc, getDoc } from "firebase/firestore";
import { auth, db, logout } from "../firebase";
import { Button, Container, Grid, Paper } from "#mui/material";
import ListDividers from "../components/ListDividers";
import { AppContext } from "../context/context";
import axios from "axios";
import {SuccessSnackbar, ErrorSnackbar} from '../components/PopupSnackbar';
import GetMavenlinkClientId from "../helpers/firebase/mavenlinkCredentials";
const Dashboard = () => {
const [user, loading, error] = useAuthState(auth);
const [name, setName] = useState("");
const [ accessToken, setAccessToken ] = useState("")
const [errorAlert, setErrorAlert] = useState(false);
const [successAlert, setSuccessAlert] = useState(false);
const [mavenlinkClientId, setMavenlinkClientId] = useState("");
const {isAuthenticated} = useContext(AppContext);
const navigate = useNavigate();
const uid = user.uid
const parsedUrl = new URL(window.location.href)
const userTokenCode = parsedUrl.searchParams.get("code");
const { mavenlinkConnected, setMavenlinkConnected } = useContext(AppContext)
const { maconomyConnected, setMaconomyConnected } = useContext(AppContext)
const { bambooConnected, setBambooConnected } = useContext(AppContext)
const fetchUserName = async () => {
try {
const q = query(collection(db, "users"), where("uid", "==", user?.uid));
const doc = await getDocs(q);
const data = doc.docs[0].data();
setName(data.name);
} catch (err) {
console.error(err);
alert("An error occured while fetching user data");
}
};
//
useEffect(() => {
if (loading) return;
if (!user) return navigate("/");
fetchUserName();
if(userTokenCode !== null){
authorizeMavenlink();
}
if(isAuthenticated){
GetMavenlinkClientId()
}
}, [user, loading]);
///put this into a page load (use effect maybe) so user does not need to press button to connect to apis
const authorizeMavenlink = () => {
console.log(uid);
const userRef = doc(db, 'users', uid);
axios({
//swap out localhost and store in variable like apitool
method: 'post',
url: 'http://localhost:5000/oauth/mavenlink?code='+userTokenCode,
data: {}
})
.then((response) => {
setAccessToken(response.data);
setDoc(userRef, { mavenlinkAccessToken: response.data}, { merge: true });
setMavenlinkConnected(true);
setSuccessAlert(true);
})
.catch((error) => {
console.log(error);
setErrorAlert(true)
});
}
//abstract out client id and pull in from db
const getMavenlinkAuthorization = () => {
window.open('https://app.mavenlink.com/oauth/authorize?client_id='+mavenlinkClientId+'&response_type=code&redirect_uri=http://localhost:3000');
window.close();
}
const authorizeBamboo = () => {
axios({
method: 'get',
url: 'http://localhost:5000/oauth/bamboo',
data: {}
})
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error);
});
// console.log('bamboo connected')
setBambooConnected(true);
}
const authorizeMaconomy = () => {
console.log("Maconomy connected")
setMaconomyConnected(true);
}
const syncAccount = async() => {
if(!mavenlinkConnected){
await getMavenlinkAuthorization()
}
if (!bambooConnected){
await authorizeBamboo();
}
if (!maconomyConnected){
await authorizeMaconomy();
}
}
const handleAlertClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setSuccessAlert(false) && setErrorAlert(false);
};
console.log(mavenlinkClientId);
return(
<>
<Container>
<div className="dashboard">
<h1>Dashboard</h1>
<Grid container spacing={2}>
<Grid item xs={12}>
<Paper style={{paddingLeft: "120px", paddingRight: "120px"}} elevation={1}>
<div className="dashboard-welcome">
<h2>Welcome {name}</h2>
<h4>{user?.email}</h4>
<hr/>
<h2>Integrations</h2>
<Button onClick={syncAccount}>
Sync Account
</Button>
{/* <Button onClick={getMavenlinkClientId}>
Bamboo Test
</Button> */}
<ListDividers/>
</div>
</Paper>
</Grid>
</Grid>
</div>
{successAlert === true ? <SuccessSnackbar open={successAlert} handleClose={handleAlertClose}/> : <></> }
{errorAlert === true ? <ErrorSnackbar open={errorAlert} handleClose={handleAlertClose}/> : <></> }
</Container>
</>
);
}
export default Dashboard;
the error is because you’re calling const {setMavenlinkClientId} = useContext(AppContext) inside the file mavenlinkCredentials.js which is not a react components.
you could maybe change the function inside mavenlinkCredentials.js to accept a setMavenlinkClientId and pass it from outside like this.
const GetMavenlinkClientId = async (setMavenlinkClientId) => {
const mavenlinkRef = doc(db, 'mavenlink', 'application_id');
const mavenlinkDocSnap = await getDoc(mavenlinkRef)
if(mavenlinkDocSnap.exists()){
console.log("mavenlink id: ", mavenlinkDocSnap.data());
console.log(mavenlinkDocSnap.data()['mavenlinkAccessToken'])
setMavenlinkClientId(mavenlinkDocSnap.data()['application_id'])
} else {
console.log("No doc");
}
}
and then you can call this function in your dashboard.js like so,
const {setMavenlinkClientId} = useContext(AppContext)
if(isAuthenticated){
GetMavenlinkClientId(setMavenlinkClientId)
}
Hi I have very common problem, react native application freezes while fetching API,
It is like when you fetching you cannot click or do anythink till your fetching ends.
This is my code where I call function which fetchs APi
import React, { useEffect, useState } from "react";
import { StyleSheet, View, FlatList } from "react-native";
// Api`s
import { topCategory } from "../../api/appModels/category";
import { banners } from "../../api/appModels/slider";
import { dinamicBlocks } from "../../api/appModels/product";
// Hooks
import useApi from "../../Hooks/useApi";
// UI-Components
import Container from "../../uicomponents/General/Container";
import BannerSlider from "../../uicomponents/Slider/BannerSlider";
import Screen from "../../uicomponents/General/Screen";
import TopProductPattern from "../../uicomponents/Category/pattern/TopProductPattern";
import SliderPlaceholder from "../../uicomponents/Skeleton/Sliders/SliderPlaceholder";
import CategoryAvatarPlaceholder from "../../uicomponents/Skeleton/Category/CategoryAvatarPlaceholder";
import CategoryBlocks from "../../uicomponents/Product/blocks/CategoryBlocks";
import Header from "../../uicomponents/header/Header";
import ActivityIndicator from "../../uicomponents/Loaders/ActivityIndicator";
const HomeScreen = () => {
const {
data: topCategoryList,
loading: topCategoryLoading,
request: categoryRequest,
} = useApi(topCategory);
const {
data: bannersList,
loading: bannerLoading,
request: bannersRequest,
} = useApi(banners);
const {
loading: blocksLoading,
request: blocksRequest,
} = useApi(dinamicBlocks);
const [blocks, setBlocks] = useState([]);
const [indexing, setIndexing] = useState(1);
const [countBlocks, setCountBlocks] = useState(0);
const [loader, setLoader] = useState(false);
useEffect(() => {
// Calling Api`s
categoryRequest();
bannersRequest();
blocksRequest((item) => {
setIndexing(indexing + 1);
setBlocks(item["blocks"]);
setCountBlocks(item["count"]);
}, 1);
}, []);
const loadMore = () => {
if (!blocksLoading) {
blocksRequest((item) => {
setIndexing(indexing + 1);
setBlocks(blocks.concat(item["blocks"]));
console.log(item);
}, indexing);
setLoader(indexing != countBlocks);
}
};
return (
<Screen>
<FlatList
data={blocks}
keyExtractor={(item) => item.categories.toString()}
ListHeaderComponent={
<>
<Header />
{bannerLoading ? (
<SliderPlaceholder />
) : (
<BannerSlider data={bannersList} dots />
)}
<Container>
<View style={{ paddingTop: 10 }}>
{topCategoryLoading ? (
<CategoryAvatarPlaceholder />
) : (
<TopProductPattern data={topCategoryList} />
)}
</View>
</Container>
</>
}
ListFooterComponent={<ActivityIndicator visible={loader} />}
renderItem={({ item }) => (
<CategoryBlocks title={item.blocks_name} data={item.categoriesList} />
)}
onEndReached={loadMore}
onEndReachedThreshold={0.1}
/>
</Screen>
);
};
export default HomeScreen;
const styles = StyleSheet.create({});
Here is my code which fetches API
import { useState } from "react";
const useApi = (apiFunc) => {
const [data, setData] = useState([]);
const [error, setError] = useState("");
const [loading, setLoading] = useState(true);
const request = async (callBack = () => {}, ...args) => {
setLoading(true);
const response = await apiFunc(...args);
if (!response.ok) return setError(response.problem);
setLoading(false);
setError("");
setData(response.data);
if (response.ok) {
callBack(response.data);
}
};
return {
data,
error,
loading,
request,
setLoading,
setData,
};
};
export default useApi;
I think there is problem with RN-bridge HELP ME PLEASE !
Probably it's happened because you set onEndReachedThreshold={0.1} and when data was loaded one more time request will be send and it's make problem.
So you can increase this value for example to 0.7.
In the official react native website This is how it is explained onEndReachedThreshold:
"How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the onEndReached callback. Thus a value of 0.5 will trigger onEndReached when the end of the content is within half the visible length of the list."