Display MONGODB data in React.js page - javascript

I am trying to display a collection from MongoDB inside a React webpage, with no success so far.
I got the data as json in the backend but I am not sure how to bring it to frontend.
The data I get looks like this:
{
_id: 60d5ee8d9f3b772030ae319c,
username: 'test',
email: 'test#test.com',
password: '$2a$10$5F8k.qfP3Bi7vlLKuOxcneejlsnxB4cN1SerV7tFkAS6v2E.YhBqK',
__v: 0
}
This is where I am trying to display the data:
import { useState, useEffect } from "react";
import axios from "axios";
import "./PrivateScreen.css";
const PrivateScreen = ({ history }) => {
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState("");
useEffect(() => {
if (!localStorage.getItem("authToken")) {
history.push("login");
}
const fetchPrivateDate = async () => {
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("authToken")}`,
},
};
try {
const { data } = await axios.get("/api/private", config);
setPrivateData(data.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}</div>
<button onClick={logoutHandler}>Logout</button>
<div>DISPLAY THE DATA HERE<div/>
</>
);
};
export default PrivateScreen;
The actual data I will get will be big, and I know I have to map it, but first I need to get to this step :D.
Could someone please give me a few hints, and sorry if I didn't give enough details, I will try and give more information if you guys require it.
Thank you, have a great day!

As you are storing the data in the privateData state, you can access that data in the whole function, here is an example of what you can do.
return error ? (
<span className="error-message">{error}</span>
) : (
<>
<div style={{ background: "green", color: "white" }}>{privateData}</div>
<button onClick={logoutHandler}>Logout</button>
<div>email: {privateData.email}, username: {privateData.username}<div/>
</>
);
or if privateData is an array you can show the data helping map, here is another example:
return error ? (
<span className="error-message">{error}</span>
) : (
<>
<div style={{ background: "green", color: "white" }}>{privateData}</div>
<button onClick={logoutHandler}>Logout</button>
<div>{privateData.map((el) => {
return (
el.username
)
})}<div/>
</>
);

Related

Fetch ApexChart data from API using axios in React

Using ApexChart I manage to display the data from a local const, but I can't display this data fetching with axios.
I can't get data result, console.log or error
File that manage the chart option
export const chartData = {
height: 460,
type: 'rangeBar',
id: 'range-chart',
options: {
chart: {
... },
series: []
};
File that display the chart
const MainChart = ({ isLoading }) => {
const [rawdata, setRawdata] = useState([]);
useEffect(() => {
const loadData = async () => {
const res = await axiosConfig.get(`/<ENDPOINT>/`)
.then(res => {
console.log('data load', res.data.record) //is showing nothing
setRawata([{
data: res.data.record
}])
}
)
}
}, [])
return (
<>
{isLoading ? (
<p>Loading...</p>
) : (
<Grid container spacing={0}>
<Grid item xs={12} mt={5}>
<Chart
options={{
...chartData.options
}}
series={[{
data: rawdata
}]}
/>
</Grid>
</Grid>
)}
</>
);
I only get options. I don't have any data result, no console log and no console error
I'm answering my own question in case help to others.
After investigating I solved my own question.
In React ApexChart you can pass all the values from one file, or split options from other values.
In the file that manage the options
export const chartData = {
// height: 460,
// type: 'rangeBar',
// id: 'range-chart',
options: {
chart: {
... },
series: []
};
Chart component. Here you pass options, series and the 3 values that you commented on the options files.
<Chart
id="range-chart"
type="rangeBar"
height={460}
options={{
...chartData.options
}}
series={
data
}
/>
The fetch issue is not related with ApexChart, but as you can guess there was a bad syntax.
const [data, setData] = useState([])
useEffect(() => {
loadData()
}, [])
const loadData = async () => {
const res = await axiosConfig.get(`<ENDPOINT>`)
setData(res.data.record)
}

don't know why im getting error while passing array of objects as props to child component in react js

I want to pass an array as props to child component and try to create table with the use of that props using react table.
I am getting this error message when passing an array as props to Table component.
Objects are not valid as a React child (found: object with keys {continent, country, totalcases, criticalcases, activecases, deaths, recovery, newcases, death1mpop, cases1mpop}). If you meant to render a collection of children, use an array instead.
App component:
function App() {
const [totalCases, setTotalCases] = useState({});
const [countryData, setCountryData] = useState([]);
const [loading, setLoading] = useState(true);
const [loadingCountry, setLoadingCountry] = useState(true);
const getCovidData = async () => {
setLoading(true);
const res = await fetch(
"https://covid-193.p.rapidapi.com/statistics?country=all",
{
method: "GET",
headers: {
"x-rapidapi-host": "covid-193.p.rapidapi.com",
"x-rapidapi-key":
"xxxxxxxxxxxxxxxxxxxxxxxxx",
},
}
);
const data = await res.json();
const actualData = data.response[0];
setTotalCases(actualData);
setLoading(false);
// console.log(actualData);
};
const getCountriesData = async () => {
setLoadingCountry(true);
const res = await fetch("https://covid-193.p.rapidapi.com/statistics", {
method: "GET",
headers: {
"x-rapidapi-host": "covid-193.p.rapidapi.com",
"x-rapidapi-key": "xxxxxxxxxxxxxxxxxxxxxxxxx",
},
});
const data = await res.json();
console.log(data.response);
let requiredData = data.response.map((d) => {
return {
continent: d.continent,
country: d.country,
totalcases: d.cases.total,
criticalcases: d.cases.critical,
activecases: d.cases.active,
deaths: d.deaths.total,
recovery: d.cases.recovered,
newcases: d.cases.new,
death1mpop: d.deaths["1M_POP"],
cases1mpop: d.cases["1M_POP"],
};
});
console.log(requiredData);
setCountryData(requiredData);
// setCountryData(data.response);
setLoadingCountry(false);
console.log(countryData);
console.log(countryData.length);
};
useEffect(() => {
getCovidData();
getCountriesData();
}, []);
return (
<div className="App">
<h1>Covid Tracker....</h1>
{loading ? <h1>Loading data</h1> : <Details totalCases={totalCases} />}
{/* {loadingCountry ? <h1>Loading list</h1>
:
<Table countryData={countryData}/>
} */}
{/* {countryData !== undefined && <Table countryData={countryData}/>} */}
</div>
);
}
export default App;
Short Answer - The error message you are getting is absolutely correct. If you read the React Docs, Your JSX compiles to React.createElement(component, props, ...children). And yes objects cannot be children. Ref - https://reactjs.org/docs/jsx-in-depth.html#children-in-jsx
Since I don't have your sample data, I am assuming your data might be like this:
<Test arr={[{ a: 1 }, { b: 2 }, { c: 3 }]} />
I am creating a small component to render this data:
import React from "react"
function Test(props) {
return (
<div>
{props.arr.map((x, index) => {
console.log(index, x);
// return <h1 key={index}>{x}</h1>;
return <h1 key={index}>{Object.keys(x).map((y) => x[y])}</h1>;
})}
</div>
);
}
If I place object in JSX, it will throw an error (Commented Code).
Also please check the Table component (if its 3rd party lib), in which format it is expecting the data. If it's yours then you have to iterate over object using Object.entries() or Object.keys(), Object.values() to display data
Hope this answers your question. Please upvote if you find it helpful.

Why can I console.log a variable but it not be able to use in a filter

I am trying to create a React.js blog so I have an easybase.io database that will hold data for my blog. There is a page where all posts are displayed, and when someone clicks on a post the post id is sent over using the paramas module in the react-router-dom package. When doing console.log(postid) it displays in the console but when passing it through the filter it doesn't work for some reason is there any explanation? The filter is filtering through all the posts selected from the database and only returning the object with the same id. When putting task.id === 1 it returns with the object with an id of 1 however when putting in task.id === postid and postid is equal to 1 in the console then it returns nothing.
All posts code
/* eslint-disable */
import { useEasybase } from "easybase-react";
import React, { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
export default function BlogPosts() {
let history = useHistory();
const { db } = useEasybase();
const [responseData, setResponse] = useState([]);
async function getPosts() {
const ebData = await db("POSTS").return().all();
setResponse(ebData);
}
useEffect(() => {
getPosts();
}, []);
return (
<>
<div>
{responseData.map((val, key) => {
return (
<div
style={{ border: "1px solid black", margin: "1em 1em" }}
key={key}
onClick={() => {
history.push(`/post/${val.id}`);
}}
>
<h3>{val.title}</h3>
<div dangerouslySetInnerHTML={{ __html: val.post_text }} />
</div>
);
})}
</div>
</>
);
}
Open post code
/* eslint-disable */
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useEasybase } from "easybase-react";
export default function BlogPosts() {
//testing for the filter function
const tasks = [
{
taskId: 1,
taskName: "Clean the bathroom",
taskStatus: "Complete",
},
{
taskId: 2,
taskName: "Learn filtering data in React",
taskStatus: "To do",
},
{
taskId: 3,
taskName: "Fix the bug on React project",
taskStatus: "To do",
},
{
taskId: 4,
taskName: "Fix the car",
taskStatus: "Complete",
},
];
const [responseData, setResponse] = useState([]);
const [idState, setIdState] = useState(0);
let { postid } = useParams();
const { db } = useEasybase();
async function getPosts() {
const ebData = await db("POSTS").return().all();
setResponse(ebData);
console.log(ebData);
}
useEffect(() => {
getPosts();
setIdState(postid);
console.log(postid);
}, []);
return (
<>
<div style={{ justifyContent: "center", alignContent: "center" }}>
{tasks
.filter((task) => task.taskStatus === "To do")
.map((task) => (
<li key={task.taskId}>{task.taskName}</li>
))}
{responseData
.filter((task) => task.id === postid)
.map((task) => (
<li key={task.id}>{task.title}</li>
))}
</div>
</>
);
}
The most likely cause is that postid from the route parameters is a string (as after all, the URL it came from is a string) while your task.id is a number as shown in your code.
When comparing '1' === 1, it'll always fail due to the types being different. Either use ==, or better, first convert the route parameter (postid) to a number.

React Invalid Hook Call While Working With Stripe

I'm implementing stripe payment to my website so I'm reading stripe payment docs. The Stripe payment document I'm following.
I even copied and pasted the code but I'm still having
Invalid Hooks Error.
I have two files one is checkoutPayment.js other one is stripeCheckoutForm.js
In stripeCheckoutForm.js
import React, { useState, useEffect } from "react";
import { CardElement, useStripe, useElements } from "#stripe/react-stripe-js";
export default function CheckoutForm() {
const [succeeded, setSucceeded] = useState(false);
const [error, setError] = useState(null);
const [processing, setProcessing] = useState("");
const [disabled, setDisabled] = useState(true);
const [clientSecret, setClientSecret] = useState("");
const stripe = useStripe();
const elements = useElements();
useEffect(() => {
window
.fetch("/create-payment-intent", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
})
.then((res) => {
return res.json();
})
.then((data) => {
setClientSecret(data.clientSecret);
});
}, []);
const cardStyle = {
style: {
base: {
color: "#32325d",
fontFamily: "Arial, sans-serif",
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#32325d",
},
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a",
},
},
};
const handleChange = async (event) => {
setDisabled(event.empty);
setError(event.error ? event.error.message : "");
};
const handleSubmit = async (ev) => {
ev.preventDefault();
setProcessing(true);
const payload = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
},
});
if (payload.error) {
setError(`Payment failed ${payload.error.message}`);
setProcessing(false);
} else {
setError(null);
setProcessing(false);
setSucceeded(true);
}
};
return (
<form id="payment-form" onSubmit={handleSubmit}>
<CardElement
id="card-element"
options={cardStyle}
onChange={handleChange}
/>
<button disabled={processing || disabled || succeeded} id="submit">
<span id="button-text">
{processing ? (
<div className="spinner" id="spinner"></div>
) : (
"Pay now"
)}
</span>
</button>
{error && (
<div className="card-error" role="alert">
{error}
</div>
)}
<p className={succeeded ? "result-message" : "result-message hidden"}>
Payment succeeded, see the result in your
<a href={`https://dashboard.stripe.com/test/payments`}>
Stripe dashboard.
</a>
Refresh the page to pay again.
</p>
</form>
);
}
In checkoutPayment.js
import React from "react";
import { loadStripe } from "#stripe/stripe-js";
import { Elements } from "#stripe/react-stripe-js";
import CheckoutForm from "./stripeCheckoutForm";
const promise = loadStripe("pk_test_6XtghloNmnIJt2Bov5bGRCAg00ozfbAMRE");
export default function App() {
return (
<div className="App">
<Elements stripe={promise}>
<CheckoutForm />
</Elements>
</div>
);
}
My error is:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem
It's so funny. It's just because of I forgot to install npm packages correctly.
npm install #stripe/react-stripe-js
npm install #stripe/stripe-js
Installing the packages resolved the problem.

React TypeError: Cannot read property 'getDates' of undefined

today i decided to update the dependencies of my react project and my component Home didn't work anymore, i'm actually working with a apollo client and apollo react hooks, this is mi Home component file:
function Home(props) {
const {
loading,
data: { getPosts: posts }
} = useQuery(FETCH_POSTS_QUERY);
return (
<Grid columns={3} stackable={true} className={loading ? 'loading' : ''}>
<Grid.Row className='page-title'>
<h1>Recent Posts</h1>
</Grid.Row>
<Grid.Row>
{user && (
<Grid.Column>
<PostForm user={user} />
</Grid.Column>
)}
{loading ? (
<Loading />
) : (
posts &&
posts.map(post=> (
<Grid.Column key={post._id} style={{ marginBottom: 20 }}>
<PostCard post={post} />
</Grid.Column>
))
)}
</Grid.Row>
</Grid>
);
}
and i'm getting this error in the browser:
"TypeError: Cannot read property 'getPosts' of undefined"
i'm trying to fix it with this little code variation:
function Home(props){
let posts = '';
const { user } = useContext(AuthContext);
const { loading, data } = useQuery(FETCH_POSTS_QUERY);
if (data) {
posts = data.getPosts;
}
And everything works fine, but if i add a new Post updating the apollo cache, that cache update correctly with old posts and new post, but the frontend didn't show it, only show old posts until i refresh the page manually.
Edit:
This is the code from the PostForm component, i updated the Home component too adding the PostForm:
function PostForm(props) {
const { values, handleChange, handleSubmit } = useForm(createPostCallback, {
title: 'Example Title',
body: ''
});
const [createPost] = useMutation(CREATE_POST_MUTATION, {
variables: values,
update(dataProxy, result) {
const data = dataProxy.readQuery({
query: FETCH_POSTS_QUERY
});
data.getPosts = [result.data.createPost, ...data.getPosts];
dataProxy.writeQuery({
query: FETCH_POSTS_QUERY,
data
});
values.body = '';
}
});
function createPostCallback() {
createPost();
}
Any idea how to fix the first code issue?
Thanks in advance mates!
I fixed same error with defining data as an object {}
just changed the below code by adding = {}
const {
loading,
data: { getPosts: posts } = {}
} = useQuery(FETCH_POSTS_QUERY);
Queries for read and write cache in apollo works in a inmutable way. In order to do that, you have to use a new variable, you're using data to write the cache.
Try doing this:
const [createPost] = useMutation(CREATE_POST_MUTATION, {
variables: values,
update (proxy, result) {
const data = proxy.readQuery({
query: FETCH_POSTS_QUERY
})
const new_post = result.data.createPost //here's the new var
proxy.writeQuery({
query: FETCH_POSTS_QUERY,
data: { getPosts: [new_post, ...data.getPosts] } // here you're using that var to write the cache
})
values.body = ''
}
})
I would take your if statement and set that inside a useEffect so it checks
if data is a truthy onLoad and so you can sync it to whenever data changes.
const [posts, setPosts] = useState([]);
useEffect(() => {
if (data) {
setPosts(data.getPosts);
}
},[data])
if (posts.length === 0) {
return <h3>No posts as of yet</h3>
}

Categories