I made a social media app and this is my homepage
import { Box, useMediaQuery } from "#mui/material";
import { useSelector } from "react-redux";
import Navbar from "scenes/navbar";
import UserWidget from "scenes/widgets/UserWidget";
import MyPostWidget from "scenes/widgets/MyPostWidget";
import PostsWidget from "scenes/widgets/PostsWidget";
import AdvertWidget from "scenes/widgets/AdvertWidget";
import FriendListWidget from "scenes/widgets/FriendListWidget";
const HomePage = () => {
const isNonMobileScreens = useMediaQuery("(min-width:1000px)");
const { _id, picturePath } = useSelector((state) => state.user);
return (
<Box>
<Navbar />
<Box
width="100%"
padding="2rem 6%"
display={isNonMobileScreens ? "flex" : "block"}
gap="0.5rem"
justifyContent="space-between"
>
<Box flexBasis={isNonMobileScreens ? "26%" : undefined}>
<UserWidget userId={_id} picturePath={picturePath} />
</Box>
<Box
flexBasis={isNonMobileScreens ? "42%" : undefined}
mt={isNonMobileScreens ? undefined : "2rem"}
>
<MyPostWidget picturePath={picturePath} />
<PostsWidget userId={_id} />
</Box>
{isNonMobileScreens && (
<Box flexBasis="26%">
<AdvertWidget />
<Box m="2rem 0" />
<FriendListWidget userId={_id} />
</Box>
)}
</Box>
</Box>
);
};
export default HomePage;
and this is my post widget
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setPosts } from "state";
import PostWidget from "./PostWidget";
const PostsWidget = ({ userId, isProfile = false }) => {
const dispatch = useDispatch();
const posts = useSelector((state) => state.posts);
const token = useSelector((state) => state.token);
const getPosts = async () => {
const response = await fetch("http://localhost:3001/posts", {
method: "GET",
headers: { Authorization: `Bearer ${token}` },
});
const data = await response.json();
dispatch(setPosts({ posts: data }));
};
const getUserPosts = async () => {
const response = await fetch(
`http://localhost:3001/posts/${userId}/posts`,
{
method: "GET",
headers: { Authorization: `Bearer ${token}` },
}
);
const data = await response.json();
dispatch(setPosts({ posts: data }));
};
useEffect(() => {
if (isProfile) {
getUserPosts();
} else {
getPosts();
}
}, []); // eslint-disable-line react-hooks/exhaustive-deps
return (
<>
{posts.map(
({
_id,
userId,
firstName,
lastName,
description,
location,
picturePath,
userPicturePath,
likes,
comments,
createdAt,
}) => (
<PostWidget
key={_id}
postId={_id}
postUserId={userId}
name={`${firstName} ${lastName}`}
description={description}
location={location}
picturePath={picturePath}
userPicturePath={userPicturePath}
likes={likes}
comments={comments}
createdAt={createdAt} // Pass the createdAt field as a prop to the PostWidget component
/>
)
)}
</>
);
};
export default PostsWidget;
when I post new post in my page old posts are staying on top and new posts are going below of the page how can I fix this. its my oldest old post post but it is top . I use mongodb and my posts hase timestamps I want to order with timestamps
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 created a Json file, and is running ok, but it doesn't insert a new item, only delete is working. Below follows the code. I'm just simulating a server with some input, delete and update, I'm working with React 18.1.0 and Material-ui.
The json data file "src/data/db.json" it loads properly from the component "Notes".
I need to insert a new item on the function handleSubmit, which is on form onSubmit.
Function to insert a new item, and after, go to the root page "/".
export default function Bancos(){
const classes = useStyles()
const history = useHistory()
const [name, setName] = useState('')
const [address, setAddress] = useState('')
const [nameError, setNameError] = useState(false)
const [addressError, setAddressError] = useState(false)
const [status, setStatus] =useState('active')
const handleSubmit = (e) => {
e.preventDefault()
setNameError(false)
setAddressError(false)
if(name == ''){
setNameError(true)
}
if(address == ''){
setAddressError(true)
}
if( name && address){
fetch('http://localhost:8000/banks', {
method: 'POST',
headers: { "Content-type": "application/json" },
body: JSON.stringify({name, address, status})
.then(() => history.push('/')),
})
}
}
return(
<Container>
<Typography variant="h6" color="textSecondary" align="center" gutterBottom
className="titleBank">
Cadastrar um novo Banco
</Typography>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
Deleting is working correctly. Why insert doesn't work?
export default function Notes(){
const [ notes, setNotes ] = useState([]);
useEffect(() => {
fetch('http://localhost:8000/banks')
.then(res => res.json())
.then(data => setNotes(data))
}, []);
const handleDelete = async (id) => {
await fetch('http://localhost:8000/banks/' + id, {
method: 'DELETE'
})
const newNotes = notes.filter(note => note.id != id) ;
setNotes(newNotes);
}
return(
<Container>
<Grid container spacing={3}>
{notes.map(note => (
<Grid item key={note.id} xs={12} md={6} lg={4}>
<CardBanks note={ note } handleDelete={handleDelete}/> {/*passing props note with element note */}
</Grid>
))}
</Grid>
</Container>
)
}
Best regards and thanks in advance.
I solved this using this code: .then was placed inside the function, so it should be placed at the end of parenthesis, next line.
import React, { useState } from 'react';
import { FormControlLabel, RadioGroup, Typography } from '#mui/material';
import { Button } from '#mui/material';
import { Container } from '#mui/material';
import KeyboardArrowRightIcon from '#mui/icons-material/KeyboardArrowRight';
import { makeStyles } from '#mui/styles';
import { TextField } from '#mui/material';
import { Radio } from '#mui/material';
import { FormLabel } from '#mui/material';
import { FormControl } from '#mui/material';
import { useHistory } from 'react-router-dom';
import '../Styles.css';
import { Box } from '#mui/material';
const useStyles = makeStyles(({
field: {
spacing: 4,
display: "block",
}
}));
export default function Bancos(){
const classes = useStyles()
const history = useHistory()
const [title, setTitle] = useState('')
const [details, setDetails] = useState('')
const [titleError, setTitleError] = useState(false)
const [detailsError, setDetailsError] = useState(false)
const [status, setStatus] =useState('active')
const handleSubmit = (e) => {
e.preventDefault()
setTitleError(false)
setDetailsError(false)
if(title == ''){
setTitleError(true)
}
if(details == ''){
setDetailsError(true)
}
if( title && details){
fetch('http://localhost:8000/notes', {
method: 'POST',
headers: { "Content-type": "application/json" },
body: JSON.stringify({ title, details, status })
})
.then(() => history.push('/'))
}
}
return(
<Container>
<Typography variant="h6" color="textSecondary" align="center" gutterBottom
className="titleBank">
Cadastrar uma nova Tarefa - Post-It
</Typography>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
I'm looking to get some help as I've been stuck on this for a while. I have a MERN stack application interacting with the Github API. Users are able to search for Github users and save them to their profile on the app and once they do that they will also start following the user on Github. In the same fashion users are able to delete the users from their profile in the app and that will unfollow the same user on Github. The problem is that when I click on the delete user button, it does not update on the browser unless I refresh the page then I see that the user is deleted from the array of saved users. In the Profile.jsx component I am rendering the list of saved users and fetching the information from the database. In the SavedGithubUsersCard.jsx component I am mapping through the saved users data to render the user's information such as name. In DeleteButton.jsx I am deleting the specific saved user when I click on the button. My question is what am I doing wrong? is the prop change not being fired or is there another issue with UseEffect?
Here is the code:
import React, { useEffect, useContext } from 'react';
import swal from 'sweetalert';
import { AppContext } from '../context/AppContext';
import SavedGithubUsersCard from './SavedGithubUsersCard';
import axios from 'axios';
Profile.jsx
const Profile = () => {
const {
githubUserData, setGithubUserData
} = useContext(AppContext);
useEffect(() => {
axios.get('/api/githubdata').then((res) => {
setGithubUserData(res.data);
})
.catch((err) => {
if (err) {
swal('Error', 'Something went wrong.', 'error');
}
});
}, [setGithubUserData]);
return (
<div className="profile-saved-users">
<div className="githubUserData-cards">
<h1 className="saved-users-header">Saved users</h1>
{!githubUserData || githubUserData.length === 0 ? (
<p className="no-saved-users-text">No saved users yet :(</p>
) : (
<SavedGithubUsersCard githubUserData={githubUserData}/>
)}
</div>
</div>
);
};
export default Profile;
import React from 'react';
import { Card, Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import DeleteButton from './DeleteButton';
SavedGithubUsersCard.jsx
const SavedGithubUsersCard = ({githubUserData}) => {
return (
<>
{githubUserData?.map(githubUserData => (
<Card key={githubUserData._id} id="saved-users-card">
<Card.Img
variant="top"
src={githubUserData.avatar_url}
id="saved-users-card-image"
/>
<Card.Body id="saved-users-card-information">
<Card.Title
id="saved-users-name"
style={{ textAlign: 'center' }}
>
{githubUserData.name}
</Card.Title>
<Card.Subtitle
id="saved-users-username"
className="mb-2 text-muted"
style={{ textAlign: 'center' }}
>
{githubUserData.login}
</Card.Subtitle>
<Card.Text id="saved-users-profile-url">
Profile URL: {githubUserData.html_url}
</Card.Text>
<Link
to={{ pathname: "githubUserData.html_url" }}
target="_blank"
>
<Button
id="saved-users-profile-button"
variant="outline-primary"
>
View profile
</Button>
</Link>
<DeleteButton githubUserDataId={githubUserData._id} githubUserDataLogin= {githubUserData.login} />
</Card.Body>
</Card>
))}
</>
);
};
export default SavedGithubUsersCard
DeleteButton.jsx
import React from 'react';
import { Button } from 'react-bootstrap';
import axios from 'axios';
import swal from 'sweetalert';
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const handleRemove = async () => {
try {
fetch(`https://api.github.com/user/following/${githubUserDataLogin}`, {
method: 'DELETE',
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`
}
});
await axios({
method: 'DELETE',
url: `/api/githubdata/${githubUserDataId}`,
withCredentials: true
});
swal(
'Removed from profile!',
`You are no longer following ${githubUserDataLogin} on Github`,
'success'
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
<Button
variant="outline-danger"
style={{ marginLeft: 20 }}
onClick={handleRemove}
id="saved-users-delete-button"
>
Remove User
</Button>
);
};
export default DeleteButton;
AppContext.jsx
import React, { createContext, useState, useEffect } from 'react';
import axios from 'axios';
const AppContext = createContext();
const AppContextProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [loading, setLoading] = useState(false);
const [githubUserData, setGithubUserData] = useState([]);
const user = sessionStorage.getItem('user');
useEffect(() => {
// incase user refreshes and context is cleared.
if (user && !currentUser) {
axios
.get(`/api/users/me`, {
withCredentials: true
})
.then(({ data }) => {
setCurrentUser(data);
})
.catch((error) => console.error(error));
}
}, [currentUser, user]);
return (
<AppContext.Provider
value={{ currentUser, setCurrentUser, loading, setLoading, githubUserData, setGithubUserData}}
>
{children}
</AppContext.Provider>
);
};
export { AppContext, AppContextProvider };
Thank you!
From what I see of your code when you delete a user you successfully delete them in the back end but don't also update the local state.
Option 1 - Refetch the users list and update local state
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
const usersDataRes = await axios.get('/api/githubdata');
setGithubUserData(usersDataRes.data);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};
Option 2 - Attempt to manually synchronize the local state
const DeleteButton = ({ githubUserDataLogin, githubUserDataId }) => {
const { setGithubUserData } = useContext(AppContext);
const handleRemove = async () => {
try {
fetch(....);
await axios(....);
swal(....);
setGithubUserData(users =>
users.filter(user => user._id !== githubUserDataId)
);
} catch (err) {
swal('Error', 'Something went wrong.', 'error');
}
};
return (
...
);
};
I want to display the Stripe subscription form after user has signed up into the extension. I want to display home to a subscribed user. And whenever the user opens the extension the home should be displayed if he has already subscribed. If not, it should display subscription form.
But the problem is my app is displaying both the home and subscription form to a subscribed user.
Here is my private route code:
const PrivateRoute = ({ component: RouteComponent, ...rest }) => {
const { currentUser, subscriptionStatus } = useContext(AuthContext);
return (
<Route
{...rest}
render={(routeProps) =>
!!currentUser ? (
!!subscriptionStatus ? (
<RouteComponent {...routeProps} />
)
: (
<Redirect to={"/subscribe"} />
)
) : (
<Redirect to={"/login"} />
)
}
/>
);
};
This is my auth context provider:
export const AuthProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [pending, setPending] = useState(true);
const [emailVerified, setEmailVerified] = useState(true);
const [helper, setHelper] = useState(false);
const [subscriptionStatus, setSubscriptionStatus] = useState(null);
useEffect(() => {
app.auth().onAuthStateChanged(async(user) => {
setCurrentUser(user);
if(!user.emailVerified){
setEmailVerified(false);
}else{
setEmailVerified(true);
const fetchData = async () => {
const token = user && (await user.getIdToken());
const payloadHeader = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
const status = await fetch('http://localhost:3000/is-subscribed', payloadHeader).then(r => r.json());
if(status == 'active'){
setSubscriptionStatus(status);
setPending(false);
}else{
setPending(false);
}
}
fetchData();
}
});
}, []);
if (pending && helper) {
return <Loader />;
}
if(!emailVerified){
return <>Please verify your email</>
}
return (
<AuthContext.Provider
value={{
currentUser, subscriptionStatus
}}
>
{children}
</AuthContext.Provider>
);
};
Any idea on this?
The easiest option would be redirecting your customers to Checkout to pay, and handling the successful payments in your Firebase app via webhooks, but you can also use the custom flow if you prefer.
Creating a notes app on MERN stack https://lutif.github.io/Notes-Keeper/ ,
I have a mongodb , I want to fetch notes on database and then render those on frontend. However reactjs doesn't allow me to initialize state (call useState) in a call back. how do it get my fetch data and use it in useState. any pointer will be helpful.
import React, { useState } from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
import CreateArea from "./CreateArea";
import addNotedb from '../APICalls/addNote';
import getNotesListdb from '../APICalls/getNotesList';
function App() {
getNotesListdb().then(nojson=>nojson.json()).then( notesListdb=>
{const [notes, setNotes] = useState([...notesListdb]);}
)
function addNote(newNote) {
// const noteId =
addNotedb(newNote);
console.log('calling add note with ', newNote);
// newNote.Id = newNote;
setNotes(prevNotes => {
return [...prevNotes, newNote];
});
}
function deleteNote(id) {
setNotes(prevNotes => {
return prevNotes.filter((noteItem, index) => {
return index !== id;
});
});
}
return (
<div>
<Header />
<CreateArea onAdd={addNote} />
{notes.map((noteItem, index) => {
return (
<Note
key={index}
id={index}
title={noteItem.title}
content={noteItem.content}
onDelete={deleteNote}
/>
);
})}
<Footer />
</div>
);
}
export default App;
const endpoint = '/api/notes';
export default function getNotes() {
let promise =
fetch(endpoint, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
}
)
return promise
}