Why does my editable input fields submit empty strings if I edit only one of the input fields? - mysql

I'm trying to create a very simple Content Management System for creating and updating blog posts. I managed to successfully create and delete blog posts but I'm having difficulty wrapping my head around when I try to edit them.
The problem I'm running into is if I have 3 fields that are Editable for the Blog Post.
1) Blog Topic
2) Blog Picture
3) Blog Content
If I edit 1 field such as Blog Topic with test data and I submit the changes, the data that was in Blog Picture and Blog Content get lost and submit nothing even though there was data there previously and I'm not sure why. However, if I set the defaultValue to my state whenever I save to make changes, the problem gets fixed but I want my inputs to have the initial value in there field also.
Here is my code:
import React from "react";
import ReactDOM from "react-dom";
import Header from "../common/Header";
import Footer from "../common/Footer";
import Adminediting from "../common/isEditing";
import Addblogtopic from "./Addblogtopic";
import { Modal, Button } from "react-bootstrap";
import { Link, Redirect } from "react-router-dom";
import Moment from "moment";
import dataTip from "data-tip";
import { confirmAlert } from "react-confirm-alert";
import CKEditor from "ckeditor4-react";
import blogtopicsService from "../../services/Blogservice";
import appController from "../../controllers/appController";
class Blogtopics extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
blogData: [],
blogCategory: "",
blogContent: "",
blogId: "",
hoverSelected: false,
isEditing: false,
fileObject: "",
fileName: "",
fileSize: "",
fileType: "",
filePayload: "",
blogPicture: "",
email: "",
firstName: "",
lastName: "",
roleId: "",
userId: "",
errorMsg2: false,
errorMsg3: false
};
}
Selectblogtopics = async () => {
const blogTopics = await blogtopicsService.selectblogTopics();
this.setState({
blogData: blogTopics
});
};
toggleHover = hoverState => {
this.setState({ hoverSelected: hoverState });
};
updateImage = e => {
let file = e.target.files[0];
var dataTypeURL = new FileReader();
var arrayBuffer = new FileReader();
this.setState({
fileObject: file,
fileName: file.name,
fileSize: file.size,
fileType: file.type
});
dataTypeURL.onload = e => {
this.setState({
filePayload: e.target.result,
blogPicture: e.target.result
});
};
dataTypeURL.readAsDataURL(file);
arrayBuffer.readAsArrayBuffer(file);
};
editBlog = editingState => {
this.setState({
isEditing: !editingState
});
//Publish Changes
setTimeout(async () => {
this.setState({
isLoading: false
});
const uploadData = {
blogCategory: this.state.blogCategory,
blogContent: this.state.blogContent,
modifiedDate: Moment().format("YYYY-MM-DD hh:mm:ss"),
blogId: this.state.blogId,
fileType: this.state.fileType,
fileName: this.state.fileName,
fileSize: this.state.fileSize,
filePayload: this.state.filePayload
};
const updateBlog = await blogtopicsService.editBlog(uploadData);
location.href = "/blog";
}, 1000);
}
};
handleClose = () => {
this.setState({ show: false });
};
handleShow = () => {
this.setState({ show: true });
};
onChange = async (e, blogId) => {
await this.setState({
[e.target.name]: e.target.value,
blogId: blogId
});
};
deleteBlog = blogId => {
confirmAlert({
customUI: ({ onClose }) => {
return (
<div className="custom-ui">
<h1>Are you sure</h1>
<p>You want to delete this blog?</p>
<button onClick={onClose}>Cancel</button>
<button
onClick={() => {
this.confirmDelete(blogId);
onClose();
}}
>
Confirm
</button>
</div>
);
}
});
};
confirmDelete = async blogId => {
// Delete the blog
const deleteBlog = await blogtopicsService.deleteBlog({ blog_id: blogId });
// Re-render the blog posts after deleting
await this.Selectblogtopics();
};
async componentDidMount() {
await this.userData();
await this.Selectblogtopics();
}
render() {
return (
<div className="fluid-container">
<div className="blogContainer">
<Header />
<Adminediting
title={this.props.match.path}
editState={this.editBlog}
/>
<div className="container">
<div className="editSection">
<div className="text-right">
<span className="data-tip-bottom" data-tip="Add Blog Post">
<i className="fas fa-plus" onClick={this.handleShow} />
</span>
</div>
</div>
<div className="blogContent">
{this.state.blogData.map((rows, index) => (
<div className="blogWrapper" key={index}>
{rows.blog_status === 1 ? (
<div
className="row"
>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add Blog Post</Modal.Title>
</Modal.Header>
<Modal.Body>
<Addblogtopic
handleClose={this.handleClose}
selectblogTopics={this.Selectblogtopics}
/>
</Modal.Body>
</Modal>
<div className="col-md-4">
<img
src={
"https://s3-us-east-1.amazonaws.com/" +
rows.blog_thumbnail
}
alt="test"
/>
{this.state.isEditing === true ? (
<div className="input-group">
<input
type="file"
className="d-block mt-4"
name="blogPicture"
onChange={e => this.updateImage(e)}
/>
</div>
) : null}
</div>
<div className="col-md-6">
{this.state.isEditing === true ? (
<input
type="text"
name="blogCategory"
onChange={e => this.onChange(e, rows.blog_id)}
defaultValue={rows.blog_category}
/>
) : (
<Link
to={
"/blog/" +
rows.blog_id +
"/" +
appController.friendlyUrl(rows.blog_category)
}
id="blogUrl"
>
<h3
id="blogTopic"
dangerouslySetInnerHTML={{
__html: rows.blog_category
}}
/>
</Link>
)}
{this.state.roleId === 1 ? (
<div className="editSection">
<div className="text-right">
<span
className="data-tip-bottom"
data-tip="Delete Blog Post"
>
<i
className="far fa-trash-alt"
onClick={e => this.deleteBlog(rows.blog_id)}
/>
</span>
</div>
</div>
) : null}
<div
className={
this.state.hoverSelected == index
? "blogSection hover"
: "blogSection"
}
>
{this.state.isEditing === true ? (
<CKEditor
data={rows.blog_content}
onChange={(event, editor) => {
const data = event.editor.getData();
this.setState({
blogContent: data
});
}}
/>
) : rows.blog_content.length > 50 ? (
<div
className="cmsStyles"
dangerouslySetInnerHTML={{
__html: rows.blog_content.substr(0, 50) + " ..."
}}
/>
) : (
<div
className="cmsStyles"
dangerouslySetInnerHTML={{
__html: rows.blog_content
}}
/>
)}
</div>
</div>
</div>
) : null}
</div>
))}
</div>
</div>
</div>
<Footer />
</div>
);
}
}
export default Blogtopics;
Back End Data
var db = require("../dbconnection");
const AWS = require("aws-sdk");
var blog = {
insertblogPost: function(data, callback) {
var uniquePicture = "blogphoto" + "-" + data.fileName;
var awsFolder = "awsfolder" + "/" + uniquePicture;
db.query(
"insert blog_topics set blog_category=?, blog_thumbnail=?, blog_content=?, blog_author=?",
[data.blogTopic, uniquePicture, data.blogContent, "random user"]
);
var buf = new Buffer(
data.filePayload.replace(/^data:image\/\w+;base64,/, ""),
"base64"
);
//Upload file into AWS S3 Bucket
var s3 = new AWS.S3();
var params = {
Bucket: "testbucket",
Key: awsFolder,
Body: buf,
ContentType: data.fileType,
ACL: "public-read"
};
s3.putObject(params, function(err, data) {
if (err) {
console.log(err, err.stack);
} else {
return data;
}
}),
callback(true);
},
deleteBlog: function(data, callback) {
db.query(
"UPDATE blog_topics set blog_status=? where blog_id=?",
["0", data.blog_id],
callback
);
},
editBlog: function(data, callback) {
var uniquePicture = "blogphoto" + "-" + data.fileName;
var awsFolder = "awsfolder" + "/" + uniquePicture;
db.query(
"UPDATE blog_topics set blog_category=?, blog_thumbnail=?, blog_content=?, blog_author=?, modified_date=? where blog_id=?",
[
data.blogCategory,
uniquePicture,
data.blogContent,
"Test Username",
data.modifiedDate,
data.blogId
]
);
var buf = new Buffer(
data.filePayload.replace(/^data:image\/\w+;base64,/, ""),
"base64"
);
//Upload file into AWS S3 Bucket
var s3 = new AWS.S3();
var params = {
Bucket: "awsbucket",
Key: awsFolder,
Body: buf,
ContentType: data.fileType,
ACL: "public-read"
};
s3.putObject(params, function(err, data) {
if (err) {
console.log(err, err.stack);
} else {
return data;
//console.log(data);
}
}),
callback(true);
},
selectblogTopics: function(data, callback) {
db.query(
"select blog_id, blog_category, blog_thumbnail, blog_content, blog_status, blog_author, created_date, modified_date from blog_topics",
callback
);
},
selectblogArticle: function(data, callback) {
db.query(
"select blog_id, blog_category, blog_thumbnail, blog_content, blog_author, created_date from blog_topics where blog_id=?",
[data.blogId],
callback
);
},
editArticle: function(data, callback) {
var uniquePicture = "blogphoto" + "-" + data.fileName;
var awsFolder = "awsfolder" + "/" + uniquePicture;
db.query(
"UPDATE blog_topics set blog_category=?, blog_thumbnail=?, blog_content=?, blog_author=?, modified_date=? where blog_id=?",
[
data.blogCategory,
uniquePicture,
data.blogContent,
"test user",
data.modifiedDate,
data.blogId
]
);
var buf = new Buffer(
data.filePayload.replace(/^data:image\/\w+;base64,/, ""),
"base64"
);
//Upload file into AWS S3 Bucket
var s3 = new AWS.S3();
var params = {
Bucket: "awsfolder",
Key: awsFolder,
Body: buf,
ContentType: data.fileType,
ACL: "public-read"
};
s3.putObject(params, function(err, data) {
if (err) {
console.log(err, err.stack);
} else {
return data;
}
}),
callback(true);
}
};
module.exports = blog;

You can create a generic method to update all blog info.
setBlogProperty(index, propName, propValue) {
this.setState(state => {
state.blogData[index][propName] = propValue;
return state;
});
};
Then call this method on onChange event of your input element.
<input
type="text"
name="blogCategory"
onChange={e => this.setBlogProperty(index, 'blog_category', e.target.value)}
defaultValue={rows.blog_category}
/>

Related

How to fetch data from a specific user

So my question is, how do i link every Item to the right users and how to fetch the data right?
I want ever user in my json db to have a multiple goalItems. As every User has a unique Id, for fetching the data only from the specific user i tried by using "fetch ('http://localhost:5000/goalItems? usersId={usersId}')" but it didn't work.
Down Below you can find the DB.json file, the FULLGOAl Component, thats where the data is fetched and the GoalItem-Component
DB.JSON
{
"users": [
{
"id": "1",
"name": "Jules",
"logindate": ""
}
],
"goalItems": [
{
"id": 1,
"usersId": "",
"text": "XY",
"completed": false,
"completedDate": "18.2.2022, 14:18:24",
"note": "XY"
},
{
"id": 2,
"usersId": "",
"text": "ZY",
"completed": true,
"completedDate": "17.2.2022, 16:40:56",
"note": "ZY"
}
]
}
FullGoal this is where the data is fetched
import React, {useState, useEffect} from 'react'
import GoalItems from './GoalItems'
import DropDownMenu from "./DropDownMenu"
import CompletedLevelPopUp from './CompletedLevelPopUp'
import {useParams} from "react-router-dom";
import levelBatch1 from "./Icons/LevelBatch1.svg"
import levelBatch2 from "./Icons/LevelBatch2.svg"
const levelOption ={
1:
["A",
"B",
"C"
],
2: ["D",
"E",
"F"
}
const FullGoal = ({setNextLevelOpen}) => {
const [editLevel, setEditLevel] = useState(true)
const [goalItems, setGoalItems] = useState ([])
const [completedDate, setCompletedDate] = useState (false)
useEffect (() => {
var completedItems = []
goalItems.forEach(g => g.completed === true | completedItems.push(g.completed))
console.log(completedItems)
if(completedItems.length > 0){
function allCompl(element) {
return element === true
}
completedItems.every(allCompl) ? setOpenPopup (true) : setOpenPopup(false)
}
}, [goalItems])
useEffect (() => {
const getGoalItems = async () => {
const goalItemsFromServer = await fetchGoalItems()
setGoalItems(goalItemsFromServer)
}
getGoalItems()
}, [])
// Fetch Goals
const fetchGoalItems = async () => {
const res = await fetch ('http://localhost:5000/goalItems? usersId={usersId}')
const data = await res.json()
return data
}
//Fetch Goal
const fetchGoal = async (id) => {
const res = await fetch (`http://localhost:5000/goalItems/${id}`)
const data = await res.json()
return data
}
const addGoal = async (goal, id) =>{
const res = await fetch (`http://localhost:5000/goalItems`, {
method:'POST',
headers:{
'Content-type': 'application/json'
},
body: JSON.stringify(goal)
})
const data= await res.json ()
setGoalItems([...goalItems, data])
}
const toggleChecked = async (id) =>{
const goalToToggle = await fetchGoal(id)
const updatedGoal = {...(goalToToggle), completed : !goalToToggle.completed , completedDate : new Date().toLocaleString() + ""}
const res = await fetch (`http://localhost:5000/goalItems/${id}`, {
method: 'PUT',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(updatedGoal)
})
const data = await res.json()
setGoalItems(goalItems.map((goal)=> goal.id === id
? {...(goal), completed: data.completed, completedDate:data.completedDate} : goal
))}
const deleteFromJson = async (id) => {
await fetch(`http://localhost:5000/goalItems/${id}`, {
method: 'DELETE'
})
setGoalItems(goalItems.filter((goal) => goal.id !== id))
}
const noteSaveJson = async (id) => {
goalItems.forEach( async e=> {
const res = await fetch (`http://localhost:5000/goalItems/${e.id}`, {
method: 'PUT',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(e)
})
})
}
useEffect (noteSaveJson, [goalItems])
return (
<div className="fullGoal">
<div className="dropDownMenuBox">
{editLevel && <DropDownMenu options={levelOption[level] || [] } onAdd={addGoal}/> }
</div>
<div className="goalItemsBox">
<GoalItems id="goalItemBox"
goalItems={goalItems}
completedDate={completedDate}
onChange={v => {
setGoalItems(v)
}}
onToggle={toggleChecked}
editLevel={editLevel}
onDelete={deleteFromJson} />
</div>
</div>
)
}
export default FullGoal
** THIS IS THE GOALITEM COMPONENT **
import React, {useState} from 'react'
import {TiDelete} from 'react-icons/ti'
import {AiFillCheckCircle} from 'react-icons/ai'
import {CgNotes} from 'react-icons/cg'
const GoalItems = ({goalItems, onToggle, editLevel, onChange, onDelete, completedDate}) => {
const [noteOpen, setNoteOpen] = useState (false)
return (
<>
{goalItems.map((goal, index)=>(
<>
<div key={goal.id} className= {`singleGoalItem ${goal.completed ? 'completed' : ''}`} onDoubleClick={()=>onToggle(goal.id)}>
<h3 id="goalTitle">{goal.text}</h3>
<CgNotes id="goalIconNote" onClick={()=> setNoteOpen(!noteOpen)}/>
{editLevel && <TiDelete id="goalIconDelete" onClick={()=> {
onDelete(goal.id)
goalItems.splice(index, 1)
onChange([...goalItems])
}}/>}
{goal.completed ? <AiFillCheckCircle id="goalIconCheck"/> : ''}
</div>
<div>
{noteOpen? <div className="noteBox">
<textarea title="Note"
type ="text"
value= {goal.note}
onChange= {(e)=> {
goalItems[index].note= e.target.value
onChange([...goalItems])}}
placeholder='Füge hier Notizen, Ideen, Pläne ein'
/> </div> : ""}
</div>
</>
))
}
</>
)
}
export default GoalItems

Data is not going in database in MERN

Data is not going in Database in MERN ---
Everything is looking fine and also got status 200 and alert "post created" but data is not going in my database.
How to debug this error. I have tried all solutions. At least tell me the possible reasons for this error. it will help me a lot.
Schema
const mongoose = require("mongoose");
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
picture: {
type: String,
required: false,
},
username: {
type: String,
required: true,
},
category: {
type: String,
required: false,
},
createDate: {
type: Date,
default: Date.now,
},
})
const post = new mongoose.model('post', postSchema);
module.exports = post;
server router
const express = require("express");
const router = express.Router();
const post = require("../schema/post-schema");
router.post('/create', async(req,res) => {
try{
console.log(req.body);
const { title, description, picture, username, category, createDate } = req.body;
const blogData = new post({
title:title,
description:description,
picture:picture,
username:username,
category:category,
createDate:createDate
});
console.log("user " + blogData);
const blogCreated = await blogData.save();
if(blogCreated)
{
return res.status(200).json({
message: "blog created successfully"
})
}
console.log("post "+post);
} catch(error){
res.status(500).json('Blog not saved '+ error)
}
})
module.exports = router;
client file
const initialValues = {
title: '',
description: '',
picture: 'jnj',
username: 'Tylor',
category: 'All',
createDate: new Date()
}
const CreateView = () => {
const [post, setPost] = useState(initialValues);
const history = useHistory();
const handleChange = (e) => {
setPost({...post, [e.target.name]:e.target.value});
}
const savePost = async() => {
try {
const {title, description, picture, username, category, createDate} = post;
console.log(post);
const res = await fetch('/create', {
method: "POST",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({title, description, picture, username, category, createDate})
})
console.log(post);
console.log("res is "+ res);
if(res.status===200 )
{
window.alert("post created");
console.log(res);
}
}
catch(e){
console.log(`save post error ${e}`);
}
}
const classes = useStyles();
const url = "https://images.unsplash.com/photo-1543128639-4cb7e6eeef1b?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8bGFwdG9wJTIwc2V0dXB8ZW58MHx8MHx8&ixlib=rb-1.2.1&w=1000&q=80";
return (
<>
<Box className={classes.container}>
<form method="POST">
<img src={url} alt="banner" className={classes.image}/>
<FormControl className={classes.form}>
<AddIcon fontSize="large" color="action" />
<InputBase placeholder="Title" className={classes.textfield} name="title" onChange={(e)=>handleChange(e)}/>
<Button variant="contained" color="primary" onClick={()=>savePost()}>Publish</Button>
</FormControl>
<TextareaAutosize aria-label="empty textarea" placeholder="Write here..." className={classes.textarea} name="description" onChange={(e)=>handleChange(e)}/>
</form>
</Box>
</>
)
}
export default CreateView;
I think problem is you checking status 200 , so your server returning status 200 in anyway as response . You have to check your server side , and check if is returning code 400 or anything else on failure .

How to load data onto a React State from an API instead of local json file?

So as part of my project I'm trying to ammend this boilerplate of React-Pdf-Highlighter to accept pdf highlights from flask-api instead of a local file( the example came with a local/json import) ..
I have tried to check with console.log the fetch is not the problem, but I feel for somereason the 'testHighlights' state is not what it should be .
<<App.js>>
// #flow
/* eslint import/no-webpack-loader-syntax: 0 */
import React, { Component } from "react";
import PDFWorker from "worker-loader!pdfjs-dist/lib/pdf.worker";
import {
PdfLoader,
PdfHighlighter,
Tip,
Highlight,
Popup,
AreaHighlight,
setPdfWorker
} from "react-pdf-highlighter";
import Spinner from "./Spinner";
import Sidebar from "./Sidebar";
import testHighlights from "./test-highlights";
import type {
T_Highlight,
T_NewHighlight
} from "react-pdf-highlighter/src/types";
import "./style/App.css";
setPdfWorker(PDFWorker);
type Props = {};
type State = {
url: string,
highlights: Array<T_Highlight>
};
const getNextId = () => String(Math.random()).slice(2);
const parseIdFromHash = () =>
document.location.hash.slice("#highlight-".length);
const resetHash = () => {
document.location.hash = "";
};
const HighlightPopup = ({ comment }) =>
comment.text ? (
<div className="Highlight__popup">
{comment.emoji} {comment.text}
</div>
) : null;
const PRIMARY_PDF_URL = "https://arxiv.org/pdf/1708.08021.pdf";
const SECONDARY_PDF_URL = "https://arxiv.org/pdf/1604.02480.pdf";
const searchParams = new URLSearchParams(document.location.search);
const initialUrl = searchParams.get("url") || PRIMARY_PDF_URL;
class App extends Component<Props, State> {
state = {
url: initialUrl,
highlights: testHighlights[initialUrl]
? [...testHighlights[initialUrl]]
: []
};
state: State;
resetHighlights = () => {
this.setState({
highlights: []
});
};
toggleDocument = () => {
const newUrl =
this.state.url === PRIMARY_PDF_URL ? SECONDARY_PDF_URL : PRIMARY_PDF_URL;
this.setState({
url: newUrl,
highlights: testHighlights[newUrl] ? [...testHighlights[newUrl]] : []
});
};
scrollViewerTo = (highlight: any) => {};
scrollToHighlightFromHash = () => {
const highlight = this.getHighlightById(parseIdFromHash());
if (highlight) {
this.scrollViewerTo(highlight);
}
};
componentDidMount() {
window.addEventListener(
"hashchange",
this.scrollToHighlightFromHash,
false
);
}
getHighlightById(id: string) {
const { highlights } = this.state;
return highlights.find(highlight => highlight.id === id);
}
addHighlight(highlight: T_NewHighlight) {
const { highlights } = this.state;
console.log("Saving highlight", highlight);
this.setState({
highlights: [{ ...highlight, id: getNextId() }, ...highlights]
});
}
updateHighlight(highlightId: string, position: Object, content: Object) {
console.log("Updating highlight", highlightId, position, content);
this.setState({
highlights: this.state.highlights.map(h => {
const {
id,
position: originalPosition,
content: originalContent,
...rest
} = h;
return id === highlightId
? {
id,
position: { ...originalPosition, ...position },
content: { ...originalContent, ...content },
...rest
}
: h;
})
});
}
render() {
const { url, highlights } = this.state;
return (
<div className="App" style={{ display: "flex", height: "100vh" }}>
<Sidebar
highlights={highlights}
resetHighlights={this.resetHighlights}
toggleDocument={this.toggleDocument}
/>
<div
style={{
height: "100vh",
width: "75vw",
position: "relative"
}}
>
<PdfLoader url={url} beforeLoad={<Spinner />}>
{pdfDocument => (
<PdfHighlighter
pdfDocument={pdfDocument}
enableAreaSelection={event => event.altKey}
onScrollChange={resetHash}
// pdfScaleValue="page-width"
scrollRef={scrollTo => {
this.scrollViewerTo = scrollTo;
this.scrollToHighlightFromHash();
}}
onSelectionFinished={(
position,
content,
hideTipAndSelection,
transformSelection
) => (
<Tip
onOpen={transformSelection}
onConfirm={comment => {
this.addHighlight({ content, position, comment });
hideTipAndSelection();
}}
/>
)}
highlightTransform={(
highlight,
index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image
);
const component = isTextHighlight ? (
<Highlight
isScrolledTo={isScrolledTo}
position={highlight.position}
comment={highlight.comment}
/>
) : (
<AreaHighlight
highlight={highlight}
onChange={boundingRect => {
this.updateHighlight(
highlight.id,
{ boundingRect: viewportToScaled(boundingRect) },
{ image: screenshot(boundingRect) }
);
}}
/>
);
return (
<Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={popupContent =>
setTip(highlight, highlight => popupContent)
}
onMouseOut={hideTip}
key={index}
children={component}
/>
);
}}
highlights={highlights}
/>
)}
</PdfLoader>
</div>
</div>
);
}
}
export default App;
<<test-highlights.js >>
const testHighlights =async () => {
const res= await fetch('http://127.0.0.1:5000/jsonapi')
const data =await res.json()
console.log(data)
this.state.testHighlights = data
return testHighlights;
}
export default testHighlights;
You can't assign state like this
this.state.testHighlights = data
You must use this.setState function to do it
this.setState({ testHighlights: data });
That is why your testHighlights state isn't what you was expected

Image uploading working on emulator, but not on real device in React-Native

Backend is Laravel and Firebase, frontend is React Native.
I tried to upload image to server on app, it is working well on emulator, but on real device.
Actually on real device when I click the upload button, the image saves to the MySQL DB correctly, but it doesn't navigate to the next page and I can't get any response. (On emulator, all works fine.)
Following is my uploading code.(react-native)
import { url } from "../config/config";
const link = "/personal_info";
export default class Personal extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
national_id: "",
email: "",
country: "US",
address: "",
company: "",
job_title: "CEO",
user_id: "",
front_image: {},
back_image: {},
front_image_upload: '',
back_image_upload: '',
};
}
SavePersonal = () => {
var myobj = this;
var apiUrl = url + link;
console.log("api is ", apiUrl);
fetch(apiUrl, {
method: "post",
body: JSON.stringify(this.state),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
}).then(function (response) {
console.log('response->', response); //--- I can't get this response.
response.json().then(function (resp) {
console.log('resp->', resp); //--- I can't get this resp.
if (resp == 0) { //--- But image saves well in MySQL DB.
Alert.alert(
"Something Went Wrong",
"Please Make Sure You Fill All Fields."
);
} else if (resp == 1) {
console.log('success->', resp);
myobj.props.navigation.push("Work");
}
});
}).catch((error) => {
console.log('personal_info_error', error);
})
};
render() {
return (
....... ........ ........
<View style={{ ...styles.margin_btm, marginTop: 20 }}>
<Button
onPress={() => {
this.SavePersonal();
}}
mode="contained"
>
Continue
</Button>
</View>
)
}
}
That is Laravel backend code.
<?php
namespace App\Http\Controllers;
use App\Personal;
use Illuminate\Http\Request;
class PersonalController extends Controller
{
function personal_info(Request $request)
{
$img = $request->front_image_upload;
// $img = explode(',', $request->front_image_upload);
$file = base64_decode($img);
$folderName = 'public/uploads/';
$safeName = uniqid().'.'.'png';
$destinationPath = public_path() . $folderName;
$success = file_put_contents(public_path().'/uploads/'.$safeName, $file);
$front_img = 'uploads/'.$safeName;
$img2 = $request->back_image_upload;
// $img2 = explode(',', $request->back_image_upload);
$file2 = base64_decode($img2);
$folderName2 = 'public/uploads/';
$safeName2 = uniqid().'.'.'png';
$destinationPath2 = public_path() . $folderName2;
$success = file_put_contents(public_path().'/uploads/'.$safeName2, $file2);
$back_img = 'uploads/'.$safeName2;
$personal = new Personal;
$personal->user_id = $request->user_id;
$personal->name = $request->name;
$personal->address = $request->address;
$personal->company = $request->company;
$personal->country = $request->country;
$personal->email = $request->email;
$personal->job_title = $request->job_title;
$personal->national_id = $request->national_id;
$personal->front_img = $front_img;
$personal->back_img = $back_img;
$personal->save();
if($personal)
{
$code = 1;
}
else
{
$code = 0;
}
return $code;
}
}
Try this. You have a problem with the .then().then().catch() grammar.
SavePersonal = () => {
// var myobj = this;
var apiUrl = url + link;
console.log("api is ", apiUrl);
fetch(apiUrl, {
method: "post",
body: JSON.stringify(this.state),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((resp) => {
console.log('---', resp);
if (resp == 0) {
Alert.alert(
"Something Went Wrong",
"Please Make Sure You Fill All Fields."
);
} else if (resp == 1) {
console.log('success = ', resp);
this.props.navigation.push("Work");
}
})
.catch((error) => {
console.log('personal_info_error', error);
})
};
you can try to pass the url in another way, instead of:
import {url} from "../config/config"
use
import {url} from "/ config / config"

How do I check whether token expired or not after user clicks on forgot password link in email

I'm trying to implement very simple forgot password functionality within my React/Node app.
I understand the following part.
1) User forgets password initiates request by entering email address.
2) Database verifies if email exists, if it does, send email with password reset link. In the link contains the route for encoded email along with special token.
Example Reset Link Request:
http://localhost:5855/forgotpasswordpage/eEJvdW5EDD1Y4Q/eyJhbGciOiJGcJhbJhb
Where the first param is the base64 encoded email and the second is JWT token.
What I'm stuck on is how do you verify that the token is still valid or not after the person has clicked on the link? Because right now, any user in my application can go to the special URL and reset there password without an expiration.
Here is my code.
Reset Password Request
import React from "react";
import forgotService from "../../services/forgotpasswordService";
import { Form, Input, Button, Row } from "antd";
import Base64 from "base-64";
class Forgotpassword extends React.Component {
constructor(props) {
super(props);
this.state = {
email: false,
successMsg: false
};
}
onSubmit(e) {
e.preventDefault();
this.props.form.validateFields(async (err, values) => {
if (!err) {
var data = {
email: values.email,
emailEncode: Base64.encode(values.email)
};
//Check if user is in the db.
const forgotcheckuserData = await forgotService.forgotcheckUser(data);
if (forgotcheckuserData.length === 0) {
this.setState({
errorMsg: true
});
this.props.form.resetFields();
} else {
this.setState({
errorMsg: false,
successMsg: true
});
this.props.form.resetFields();
const forgotpasswordData = await forgotService.emailUser(data);
}
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className="form-container">
<div className="forgotpasswordContainer">
{/* User does not exist */}
{this.state.errorMsg === true ? (
<span style={{ color: "red" }}>
That email address does not exist in our system.
</span>
) : null}
{/* Success. Send forgot password email */}
{this.state.successMsg === true ? (
<span style={{ color: "green" }}>
Success. Please check your email to reset your password.
</span>
) : null}
<Form layout="inline" onSubmit={e => this.onSubmit(e)}>
<Row>
<Form.Item>
{getFieldDecorator("email", {
rules: [
{ type: "email", message: "That is not a valid email!" },
{
required: true,
message: "Please put in an email address"
}
]
})(<Input placeholder="Email Address" />)}
</Form.Item>
</Row>
<Row>
<Button type="primary" id="loginButton" htmlType="submit">
Submit
</Button>
</Row>
</Form>
</div>
</div>
);
}
}
const ForgotWrapper = Form.create({ name: "forgot_form" })(Forgotpassword);
export default ForgotWrapper;
BackEnd
var db = require("../dbconnection");
var forgotpasswordMail = require("./Forgotpasswordmail");
var SHA256 = require("sha256");
var nodemailer = require("nodemailer");
var inlineCss = require("nodemailer-juice");
var jwt = require("jsonwebtoken");
var forgotPassword = {
forgotcheckUser: function(data, callback) {
db.query("select * from users where email=?", [data.email], callback);
},
forgotAuth: function(data, callback) {
var datetime = new Date();
var dateModified =
datetime.getFullYear() +
"-" +
(datetime.getMonth() + 1) +
"-" +
datetime.getDate();
var password = SHA256(data.password);
var confirmPassword = SHA256(data.confirmPassword);
console.log(data);
db.query(
"UPDATE users set password=?, confirmpassword=?, dateModified=? WHERE email=?",
[password, confirmPassword, dateModified, data.emailId]
);
},
emailUser: function(data, callback) {
var resetToken = jwt.sign(
{
data: data.email,
exp: Math.floor(Date.now() / 1000) + 60 * 60 // 1 hour
},
"secretToken"
);
var emailData = {
email: data.email,
emailEncoded: data.emailEncode,
resetpasswordToken: resetToken
};
let transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
pass: "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
// TLS is for localhost only, disable once on production.
tls: {
rejectUnauthorized: false,
debug: true
}
});
let mailOptions = {
from: "xxxxxxxxxxxxxxxxxx",
to: data.email,
subject: "Forgot Password Request",
html: forgotpasswordMail.forgotTemplate(emailData)
};
// Nodemailer Juice Configuration Options
transporter.use("compile", inlineCss(mailOptions));
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log("Message sent: %s", info.messageId);
}
});
}
};
module.exports = forgotPassword;
Reset Password Page (After user clicks on password reset link.)
import React from "react";
import forgotService from "../../services/forgotpasswordService";
import Base64 from "base-64";
import { Form, Button, Row, Col, Icon, Tooltip, Input } from "antd";
import { PasswordInput } from "antd-password-input-strength";
import Headericons from "../common/header-icons";
import Header from "../common/header";
import Footer from "../common/footer";
class Forgotpasswordemail extends React.Component {
constructor(props) {
super(props);
this.state = {
emailId: Base64.decode(this.props.match.params.id),
password: "",
confirmPassword: "",
capslockEnabled: false,
errorMsg: false,
errorMsg2: false,
successMsg: false
};
}
compareToFirstPassword = (rule, value, callback) => {
const { form } = this.props;
if (value && value !== form.getFieldValue("password")) {
callback("Two passwords that you enter is inconsistent!");
} else {
callback();
}
};
validateToNextPassword = (rule, value, callback) => {
const { form } = this.props;
if (value && this.state.confirmDirty) {
form.validateFields(["confirm"], { force: true });
}
callback();
};
async onSubmit(e) {
e.preventDefault();
this.props.form.validateFields(async (err, values) => {
if (!err) {
const emailId = Base64.decode(this.props.match.params.id);
// const data = {
// emailId: emailId,
// password: values.password,
// confirmPassword: values.confirmPassword
// };
//const forgotpasswordData = await forgotService.forgotAuth(data);
this.props.form.resetFields();
}
});
}
render() {
console.log(this.props.match.params);
const { getFieldDecorator } = this.props.form;
return (
<div className="container-fluid" id="forgotpasswordemail">
<Headericons />
<Header />
<div className="container">
<div className="genericcontainer">
<h1>RESET YOUR PASSWORD</h1>
{/* Not identical passwords */}
{this.state.errorMsg2 !== false ? (
<span id="forgotunique" style={{ color: "red" }}>
Passwords are not the same.
</span>
) : null}
{/* Success. Change users password */}
{this.state.successMsg !== false ? (
<span id="forgotunique" style={{ color: "green" }}>
Password Successfully Changed.
</span>
) : null}
<div className="forgotpasswordContainer">
<Form layout="inline" onSubmit={e => this.onSubmit(e)}>
<Row type="flex" justify="center">
<Form.Item>
<Input
prefix={
<Icon
type="user"
style={{ color: "rgba(0,0,0,.25)" }}
></Icon>
}
disabled
value={this.state.emailId}
/>
</Form.Item>
</Row>
<Row type="flex" justify="center">
<Form.Item>
{getFieldDecorator("password", {
rules: [
{
required: true,
message: "Please enter a new password"
},
{
required: true,
pattern:
"^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[##$%^&+*!=]).*$",
message:
"Password must contain 1 uppercase, 1 lowercase and 1 special character"
},
{
required: true,
min: 8,
message: "Password must be 8 characters or longer"
},
{
validator: this.validateToNextPassword
}
]
})(
<PasswordInput
prefix={
<Icon
type="lock"
style={{ color: "rgba(0,0,0,.25)" }}
></Icon>
}
placeholder="Password"
/>
)}
</Form.Item>
</Row>
<Row type="flex" justify="center">
<Form.Item>
{getFieldDecorator("confirmPassword", {
rules: [
{
required: true,
message: "Please confirm your password!"
},
{
validator: this.compareToFirstPassword
}
]
})(
<PasswordInput
prefix={
<Icon
type="lock"
style={{ color: "rgba(0,0,0,.25)" }}
></Icon>
}
placeholder="Confirm Password"
/>
)}
</Form.Item>
</Row>
<Row type="flex" justify="center">
<Button type="primary" htmlType="submit" id="resetButton">
Reset Password
</Button>
</Row>
</Form>
</div>
</div>
</div>
<Footer />
</div>
);
}
}
const ForgotPasswordWrapper = Form.create({ name: "forgot_password_form" })(
Forgotpasswordemail
);
export default ForgotPasswordWrapper;