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}>
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 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
I have a page which shows some collections from my firestore database, I am struggling to work out how to use the orderBy function to show the documents in a specific order.
I'm not sure where to put orderBy in the code. I would like to order them by a field from the firestore documents called 'section'.
I've been trying this week following other tutorials and answers from StackOverflow but can't yet work it out.
import React, { useEffect, useState, Component, setState } from 'react';
import { collection, getDocs, getDoc, doc, orderBy, query } from 'firebase/firestore';
import "./AllSections.css";
import { Firestoredb } from "../../../../../firebase.js";
import AllCourses from './AllCourses';
import ReactPlayer from 'react-player'
import ViewSection from './ViewSection';
import SectionsTabData from './SectionsTabData';
import {
BrowserRouter as Router,
Link,
Route,
Routes,
useParams,
} from "react-router-dom";
import VideoJS from './VideoJS';
function SectionsData() {
const videoJsOptions = {
controls: true,
sources: [{
src: sectionVideo,
type: 'video/mp4'
}]
}
const {courseId} = useParams();
const {collectionId} = useParams();
const params = useParams();
const [sectionId, setSectionId] = useState('');
const [sectionImage, setSectionImage] = useState('');
const [sectionVideo, setSectionVideo] = useState('');
const [sectionContent, setSectionContent] = useState('');
const [isShown, setIsShown] = useState(false);
const handleClick = event => {
// 👇️ toggle shown state
setIsShown(current => !current);
}
const [active, setActive] = useState();
const [id, setID] = useState("");
const [Sections, setCourses, error, setError] = useState([]);
useEffect(() => {
getSections()
}, [])
useEffect(() =>{
console.log(Sections)
}, [Sections])
function getSections() {
const sectionsCollectionRef = collection(Firestoredb, collectionId, courseId, 'Sections');
orderBy('section')
getDocs(sectionsCollectionRef)
.then(response => {
const content = response.docs.map(doc => ({
data: doc.data(),
id: doc.id,
}))
setCourses(content)
})
.catch(error => console.log(error.messaage))
}
const handleCheck = (id, image, video, content) => {
console.log(`key: ${id}`)
/*alert(image)*/
setSectionId(id)
setSectionImage(image)
setSectionVideo(video)
setSectionContent(content)
}
return (
<>
<div className='MainSections'>
<div className='Sidebar2'>
<ul className='SectionContainer'
>
{Sections.map(section => <li className='OneSection' key={section.id}
style={{
width: isShown ? '100%' : '200px',
height: isShown ? '100%' : '50px',
}}
onClick={() =>
handleCheck(section.id, section.data.thumbnailImageURLString, section.data.videoURLString, section.data.contentURLString)}
id = {section.id}
>
<br />
{section.data.name}
<br />
<br />
{isShown && (
<img className='SectionImage' src={section.data.thumbnailImageURLString !== "" ? (section.data.thumbnailImageURLString) : null} alt='section image'></img>
)}
<br />
</li>)}
</ul>
</div>
<div className='ViewSection'>
<iframe className='Content' src={sectionContent}
width="100%"/>
</div>
</div>
</>
)
}
export default SectionsData
You are using orderBy incorrectly please view the docs here: https://firebase.google.com/docs/firestore/query-data/order-limit-data
Your query should look something along these lines if you're trying to order your data in a specific way. Assuming your sectionsCollectionRef is correct:
const sectionsCollectionRef = collection(Firestoredb, collectionId, courseId, 'Sections')
const q = query(sectionsCollectionRef, orderBy('section', 'desc'))
const querySnapshot = await getDocs(q);
The orderBy() won't do anything on it's own. You must use it along query() function to add the required QueryConstraint and build a Query as shown below:
import { collection, query } from "firebase/firestore"
const sectionsCollectionRef = collection(Firestoredb, collectionId, courseId, 'Sections');
const sectionsQueryRef = query(sectionsCollectionRef, orderBy("section"))
I am using react-select with more than 20,000 options fetched from the database via Node API.
Page was not even loading .
Now, I added "react-select-async-pagination".
But the data is fetched once only.
import React, { useRef, useState, useEffect } from "react";
import Select from "react-select";
import LoadOptions from "./LoadOptions";
import { AsyncPaginate } from "react-select-async-paginate";
const TooManySelect = () => {
const [value, onChange] = useState(null);
return (
<div className="Select-options">
<label>Pdt code</label>
<AsyncPaginate
defaultOptions
value={value}
loadOptions={LoadOptions}
onChange={onChange}
/>
</div>
);
};
export default TooManySelect;
LoadOptions : Here is the api call. I am passing the count of the last row fetched every time via "prevLast" so that I can use the OFFSET prevLast ROWS inside database query.
import { useState } from "react";
const sleep = (ms) =>
new Promise((resolve) => {
setTimeout(() => {
resolve();
}, ms);
});
const baseurl = "http://localhost:5000/api";
const LoadOptions = async (search, prevOptions) => {
const [prevLast, setPrevLast] = useState(0);
const [pdtOpt, setPdtOpt] = useState([]);
await sleep(1000);
const response = await fetch(`${baseurl}/pdt/${prevLast}`);
const pList = await response.json();
const pdtList = [];
for (let i = 0; i < pList.length; i++) {
pdtList.push({ label: pList[i].pdtno, value: pList[i].pdtno });
}
setPdtOpt(pdtList);
setPrevLast(pList.length);
return {
options: pdtList,
hasMore: true
};
};
export default LoadOptions;
Here is my codesandbox link.
https://codesandbox.io/s/react-select-paginate-test-tob90j
My question is : How can we access thousands of (select) options from DB without page freeze?
I got this link while googleing.
https://blog.saeloun.com/2022/03/03/infinite-scroll-with-pagination.html#using-lazy-loading-and-pagination
It helped me came to a perfect solution.
So my current code goes like this
(Made only a few changes from the code given in the above link).
Select component:
import React, { useState } from "react";
import SelectWrapper from "./SelectWrapper";
const baseurl = "http://localhost:5000/api";
function MainSelect() {
const [options, setOptions] = useState([]);
const [selectedOption, setSelectedOption] = useState("");
const [pageNo, setPageNo] = useState(0);
const [hasNextPage, setHasNextPage] = useState(true);
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
const loadOptions = async (page) => {
try {
// console.log(`Page ${page}`);
const size = 50;
setIsNextPageLoading(true);
const data = await fetch(`${baseurl}/pdt/${page}/${size}`);
const pList = await data.json();
const pdtList = [];
for (let i = 0; i < pList.length; i++) {
pdtList.push({ label: pList[i].pdtno, value: pList[i].pdtno });
}
setOptions(pdtList);
setIsNextPageLoading(false);
setHasNextPage(pdtList.length < 500);
setPageNo(page);
} catch (err) {
console.log(err);
}
};
console.log(options);
const loadNextPage = async () => {
await loadOptions(pageNo + 1);
};
return (
<div className="dropdown">
<div className="dropdown">
<div className="label">
<label>Pdt</label>
</div>
<SelectWrapper
value={selectedOption}
placeholder="Select"
isClearable
hasNextPage={hasNextPage}
isNextPageLoading={isNextPageLoading}
options={options}
loadNextPage={loadNextPage}
onChange={(selected) => setSelectedOption(selected)}
/>
</div>
</div>
);
}
export default MainSelect;
SelectWrapper that carries out the Virtualization part:
import React, { useEffect, useState } from "react";
import { FixedSizeList as List } from "react-window";
import InfiniteLoader from "react-window-infinite-loader";
import Select from "react-select";
import AutoSizer from "react-virtualized-auto-sizer";
const SelectWrapper = (props) => {
const {
hasNextPage,
isNextPageLoading,
options,
loadNextPage,
placeholder,
onChange,
value,
} = props;
const [selectedOption, setSelectedOption] = useState(value);
useEffect(() => {
setSelectedOption(value);
}, [value]);
const itemCount = hasNextPage ? options.length + 1 : options.length;
const loadMoreItems = isNextPageLoading ? () => {} : loadNextPage;
const isItemLoaded = (index) => !hasNextPage || index < options.length;
const MenuList = ({ children }) => {
const childrenArray = React.Children.toArray(children);
const Item = ({ index, style, ...rest }) => {
const child = childrenArray[index];
return (
<div
className="drop-down-list"
style={{
borderBottom: "1px solid rgb(243 234 234 / 72%)",
display: "flex",
alignItems: "center",
...style,
}}
onClick={() => handleChange(options[index])}
{...rest}
>
{isItemLoaded(index) && child ? child : `Loading...`}
</div>
);
};
return (
<AutoSizer disableHeight>
{({ width }) => (
<InfiniteLoader
isItemLoaded={(index) => index < options.length}
itemCount={itemCount}
loadMoreItems={loadMoreItems}
>
{({ onItemsRendered, ref }) => (
<List
className="List"
height={150}
itemCount={itemCount}
itemSize={35}
onItemsRendered={onItemsRendered}
ref={ref}
width={width}
overscanCount={4}
>
{Item}
</List>
)}
</InfiniteLoader>
)}
</AutoSizer>
);
};
const handleChange = (selected) => {
console.log("test");
onChange(selected);
};
return (
<Select
placeholder={placeholder}
components={{ MenuList }}
value={selectedOption}
options={options}
{...props}
/>
);
};
export default SelectWrapper;
For anyone who needs the same, I have updated the codepen as well.
https://codesandbox.io/s/react-select-paginate-test-tob90j
I made a json server, after installation globally, everything is working, and the command "npx json-server --watch src/data/db.json --port 8000" to watch the data from file db.json, on port 8000, is working properly, it loads the data, and also delete, but does not insert a new item. So I need help please to fix this situation. This server is just for production mode for my application in React 18.1 and nodejs. I'm using Material-ui as well.
Below my code to insert and delete data.
import React, { useEffect, useState } from 'react';
import { Container, Grid } from '#mui/material';
import CardBanks from '../components/CardBanks';
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>
)
}
// Inserting a new Bank (Bank component)
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,
margimTop: 50,
marginBottom: 100,
display: "block",
}
}));
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}>
After fetching a new Bank, I do a push to "/" root and it doesn't go to the root page.
Follow the message of delete, but I'm not getting error message on fetching the post.
Loading src/data/db.json
Done
Resources
http://localhost:8000/banks
Home
http://localhost:8000
Type s + enter at any time to create a snapshot of the database
Watching...
GET /banks 304 25.153 ms - -
GET /banks 304 5.086 ms - -
GET /banks 304 3.618 ms - -
GET /banks 304 4.286 ms - -
GET /banks 304 3.166 ms - -
DELETE /banks/4 200 7.424 ms - 2