Why won't my Modal open on a successful api call - axios

I designed a modal using Material UI that I am importing and passing props to. I'm trying to have the modal open in either the .then block or the .catch of the axios call. It opens in the .catch but not in the .then though I have other operations occurring without a problem in the .then block. Also all of the state is properly being set confirmed via console.log for the modal to open. If I remove the code from the .then block the modal opens fine.
This is just a snippet of the code. I removed all the other .then operations to make the code more simple. Any ideas would be appreciative.
import { ResponseModal } from "components/Modals/ApiResponse-Modal";
export const ImportDataProperties = ({ element }) => {
const [responseMessage, setResponseMessage] = useState("");
const [type, setType] = useState("");
const [modalOpen, setmodalOpen] = useState(false);
const handleClose = () => setmodalOpen(false);
const handleSave = () => {
axios
.post("dshservices/api/Dataset/UploadFile", 'example data')
.then((res) => {
const { dateCreated, id, databaseName, schemaName, tableName } = res.data.value;
setResponseMessage(`time of success: ${dateCreated}`);
setType("success");
setmodalOpen(true);
})
.catch((error) => {
setResponseMessage(
`time of error: ${new Date().toLocaleDateString() + " (CST)*"}, ${error}`
);
setType("error");
setmodalOpen(true);
});
};
return (
<Content>
<Button onClick={handleSave} disabled={disabled} variant="contained">
UPLOAD FILE
</Button>
<ResponseModal
message={responseMessage}
type={type}
handleClose={handleClose}
open={modalOpen}
/>
</Content>
);
};

Related

How to stop getting an undefined value when changing a select value using useState and useEffect

I have the following code in my first component, where I fetch some data from which I need to pull an array of strings and send it as values to my Material UI select component:
const Logs = () => {
const [data, setData] = useState({})
const [usersList, setUsersList] = useState([])
const [user, setUser] = useState(null)
const getData = async () => {
try {
const { data } = await axios.request({
method: "GET",
baseURL: 'some url',
url: `/logger`,
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
});
setData(data);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
( async () => {
await getData();
})()
}, []);
const isEmpty = obj => Object.keys(obj).length === 0;
useEffect(() => {
if(isEmpty(data) === false) {
setUsersList(data.userNames)
}
console.log('Data', data) //{userNames: ['Admin', 'User1', 'User2']
})
useEffect(() => {
setUser(usersList[0]) //setting the user to Admin
})
const handleUserChange = (event) => {
const value = event.target.value;
setUser(value);
};
return (
<div>
<CssBaseline />
{<LogsSelect
labelId="logs-user-select-label"
selectId="logs-user-select"
handleChange={handleUserChange}
value={user}
list={usersList}
label='User'
/>
}
)
}
My select is defined as a separate (generic) component:
const LogsSelect = (labelId, selectId, handleChange, value, list, label) => {
return (
<FormControl
className={classes.form}
style={{ minWidth: "140px"}}
>
<InputLabel id={labelId}>{label}</InputLabel>
<Select
className={classes.select}
labelId={labelId}
id={selectId}
onChange={handleChange}
value={value}
>
{value && list?.map((el, index) => (
<MenuItem value={el} key={index}>
{el}
</MenuItem>
))}
</Select>
</FormControl>
)}
I get the following error:
Material-UI: You have provided an out-of-range value undefined for the select component.
Consider providing a value that matches one of the available options or ''.
The available values are "". This is happening when rendering the components. I haven't even managed to get my list of values as options in my select, and then try and change the value.
Pass defaultValue="" to the <Select />
...
<Select
defaultValue=""
>
...
</Select>
...

NextJS 13 fails to fetch from internal api route when deploying

When fetching from /api in npm run dev or npm run build/start my code is working, but when try to deploy it on Vercel it fails to fetch. Im using Next js 13 with app dir.
here is my code on the client (server component)
`const getAvailableSlots = async () => {
const res = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/availabilityList`
);
if (!res.ok) {
console.log(res);
}
return res.json();
};
const Appointments = async () => {
const data = await getAvailableSlots();
return (
<div className="App">
<div>
<AppointmentsPage data={data} />
</div>
</div>
);
};
export default Appointments;`
and this is the /api route:
`const handler = async (req, res) => {
await connectDB();
console.log("Connected to Mongo");
try {
const availiblityList = await Users.find();
res.status(200).send(availiblityList);
} catch (error) {
res.status(400).send(error.message);
}
};
export default handler;`
I tried directly accessing the data from the server since its server components, but in development mode it loads on the first time with warning that only can pass down simple object as props and can't reload after that.
`import { getData } from "../../pages/api/availabilityList";
const getAvailableSlots = async () => {
const res = await getData();
return res;
};
const Appointments = async () => {
const data = await getAvailableSlots();
console.log(data);
return (
<div className="App">
<div className="section section0 fp-auto-height-responsive items-center">
<AppointmentsPage data={data} />
</div>
</div>
);
};
export default Appointments;`
/api
`export async function getData() {
await connectDB();
const response = await Users.find();
return response;
}
const handler = async (req, res) => {
const jsonData = await getData();
res.status(200).json(jsonData);
};
export default handler;`
The Warning:
Warning: Only plain objects can be passed to Client Components from Server Components. Objects with toJSON methods are not supported. Convert it manually to a simple value before passing it to props. [{$__: ..., $isNew: false, _doc: ...}, ...]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

React useEffect hook running infinite loop despite static dependencies

Can someone please point to me what part of this code is causing an infinite loop?
I have tried wrapping this in useCallback as well but it still runs forever.
slug is the page url that will not change over time
likesCollectionRef is also goint to remain constant
isAuth can change overtime depending on if the user is logged in or out
export default function CommentForm({ slug, isAuth, setReloadTS }) {
const [isLiked, setIsLiked] = useState(false);
const likesCollectionRef = collection(fireStore, 'likes');
useEffect(() => {
if (!isAuth) return;
const qry = query(
likesCollectionRef,
where('slug', '==', slug),
where('author.id', '==', auth.currentUser.uid)
);
const findLike = async () => {
const data = await getDocs(qry);
console.log(`initial like: ${data.docs}`);
setIsLiked(data.docs !== 'undefined' && data.docs);
};
findLike();
}, [slug, isAuth, likesCollectionRef]);
}
likesCollectionRef is declared each render cycle. Place the likes collection reference in a React ref so it's a stable reference. auth also appears to be an external dependency. If it's external to the component this is ok, but if it's internal to the component it should be added to the dependency array.
export default function CommentForm({ slug, isAuth, setReloadTS }) {
const [isLiked, setIsLiked] = useState(false);
const likesCollectionRef = useref(collection(fireStore, 'likes'));
useEffect(() => {
if (!isAuth) return;
const qry = query(
likesCollectionRef.current,
where('slug', '==', slug),
where('author.id', '==', auth.currentUser.uid)
);
const findLike = async () => {
const data = await getDocs(qry);
console.log(`initial like: ${data.docs}`);
setIsLiked(data.docs !== 'undefined' && data.docs);
};
findLike();
}, [isAuth, likesCollectionRef, slug]);
...
}

React app with axios inside useEffect() is rendering twice

I've been trying to figure out why my function that draws a BPMN diagram is rendering the diagram twice. I have looked at various examples using axios inside useEffect but cannot figure out why it is happening. The url is returning a valid xml for the viewer.
Can anyone give me some guidance?
Here is the entire function
function RenderBPMN(pathDefinition) {
const [diagram, setDiagram] = useState("");
const container = document.getElementById("container");
const msg = JSON.stringify(pathDefinition);
const url = `http://localhost:9090/xml?path=${msg}`;
useEffect(() => {
const fetchData = async () => {
axios
.get(url)
.then((resp) => {
setDiagram(resp.data);
})
.catch ((error) => {
console.log(error);
});
};
fetchData();
}, [url]);
if (diagram.length > 0) {
const viewer = new Viewer({
container,
keyboard: {
bindTo: document
}
});
viewer
.importXML(diagram)
.then(({ warnings }) => {
if (warnings.length) {
console.log("Warnings", warnings);
}
viewer.get('canvas').zoom('fit-viewport');
})
.catch((err) => {
console.log("error", err.message);
});
}
return (
<div
id="container"
style={{
border: "1px solid #010101",
height: "50vh",
width: "70vw",
margin: "auto"
}}
></div>
);
}
export default RenderBPMN;
Remove url from useEffect array. With empty array it will by called only once when component will be mounted.
useEffect( () => {
// your code
}, [ /* empty */ ])

How to Use Rest api with React Native; Network Call Issues

I am newbie in React Native,
I made a simple back-end using Mongodb and express routes etc in MongoDb atlas. I am successfully able to post/get/patch/Delete operation on mongodb atlas that store Title and Description using Postman. Everything is working fine.
Here comes the problem First when i make a simple frontend in ReactNative that take inputs Title and Description. I want application that take simple input of Title and Description and on Submit Button it store into the the mongodb Atlas just like postman is doing. I tried but its not working code is below. I dont know how to communicate the front end into backend. I watch alot of tutorials but unable to get the point.
Secondly, when i make a server i wrote in pakage.json > "start": "nodemone server.js" and i need to run ReactNative app i update the pakage.json > "start": "expo start" to run app. How can i run server and expo app same time? if i seprate the app folder then how can i connect both of them.
below is my Code.
Routes folder post.js
const express = require( 'express' );
const router = express.Router();
const Post = require ('../models/Post')
//Gets back all the posts
router.get ( '/', async (req, res) =>{
try{
const post = await Post.find();
res.json(post);
}catch (err) {
res.json({message: err })
}
});
//To Submit the Post
router.post('/', async (req, res) =>{
//console.log(req.body);
const post = new Post({
title: req.body.title,
description: req.body.description
});
try{
const savedPost = await post.save();
res.json(savedPost);
}catch (err) {
res.json ({ message: err })
}
});
//Get back specific Post
router.get('/:postId', async (req, res) =>{
try{
const post= await Post.findById(req.params.postId);
res.json(post);
}catch(err) {
res.json({message: err });
}
})
// to delete specific post
router.delete('/:postId', async (req, res) =>{
try{
const removePost= await Post.remove({_id: req.params.postId});
res.json(removePost);
}catch(err) {
res.json({message: err });
}
})
//update Post
router.patch('/:postId', async (req, res) =>{
try{
const updatePost = await Post.updateOne(
{_id: req.params.postId},
{ $set:
{title: req.body.title}
});
res.json(updatePost);
}catch(err) {
res.json({message: err });
}
})
module.exports = router;
Defined Schema Post.js
const mongoos = require( 'mongoose' );
const PostSchema = mongoos.Schema ({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
})
module.exports = mongoos.model ('Post', PostSchema); // giving this schma name Post
server.js
const express = require( 'express' );
const app = express();
var mongo = require('mongodb');
const mongoos = require( 'mongoose' );
const bodyParser = require('body-parser');
require('dotenv/config');
const postRoute = require('./Routes/post');
app.use(bodyParser.json());
app.use ('/post', postRoute);
app.get ( '/', (req, res) =>{
res.send('We are on Home ')
});
// connecting to database
mongoos.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true },
() => console.log('Connected to db')
);
app.listen(3000);
Frontend Form.js
import React from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
class Form extends React.Component{
constructor(){
super();
this.State = {
title: '',
description: ''
}
}
getInput(text, field){
if(field == 'title')
{
this.setState({ title: text, })
}
else if(field == 'description')
{
this.setState({ description: text, })
}
//console.warn(text)
}
submit(){
let collection={}
collection.title = this.state.title,
collection.description = this.state.description;
console.warn(collection);
var url = process.env.DB_CONNECTION ;
fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
collection
}),
});
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.inputBox}
underlineColorAndroid= 'rgba(0,0,0,0)'
placeholder='Title'
selectionColor="#fff"
keyboardType="default"
onChangeText = {(text) => this.getInput(text, 'title')}
/>
<TextInput style={styles.inputBox}
multiline = {true}
numberOfLines = {4}
underlineColorAndroid= 'rgba(0,0,0,0)'
placeholder='Description'
selectionColor="#fff"
keyboardType="default"
onChangeText= {(text) => this.getInput(text, 'description')}
/>
<TouchableOpacity onPress={()=>this.submit()} style={styles.btn} >
<Text style={{textAlign: 'center'}}>Submit</Text>
</TouchableOpacity>
</View>
);
}
}
export default Form;
Here comes a very basic solution to your problem:
1: if you are using Rest API based model of communication go for Two separate repos on GITHUB. One for React native app of yours and one for server-side of yours.
2: now to go to Heroku.com and make an app there and attach your card there in order to use the full Free Sandbox functionality
3: create a project there and find an option to deploy from Github.
4: for data communication aka network requests its easy to use axios rather than Fetch
for best practices use :
https://riptutorial.com/react-native/topic/857/getting-started-with-react-native
5: in order to run more than one command in package json able to run multiple scripts in package.json you can either do it like
scripts:{"run": "yarn start" && "react-native-expo"}
6: or if your scripts are like they gonna need to run constantly in the background it's better that you create two separate scripts
scripts:{"run1": "yarn start", "run2":"yarn start2"}
7: I see you are not handling the AsyncAwait Try catch or Promise after the fetch
8: you are also not hitting the server-side URL seemingly you are hitting DB connection url. what you should be doing is that you hit the POST/GET/UPDATE routing endpoint of yours