React-quil nextjs use problem ref not work - javascript

When I connect NEXTJS react-quill, quill does not work.
screen error
I have attached a quill to my site. When I connected Quill the codes were class component. then I switched to arrow function. There was an error while processing
create.js file:
import React, { useState, useRef } from "react";
import dynamic from "next/dynamic";
import axios from "axios";
import Main from "../../layouts/main";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import cookie from "react-cookies";
import { withRouter } from "next/router";
import Link from "next/link";
const MyComponent = (props) => {
const [state, setState] = useState({
editorHtml: "",
title: "",
image: {},
message: "",
error_message: "",
error_type: "",
category_id: 1,
token: cookie.load("userToken"),
});
const handleChange = (html) => {
setState({ editorHtml: html });
};
const selectImage = (image) => {
console.log(image);
};
const onSubmitForm = (event) => {
event.preventDefault();
const image = document.querySelector("#image").files[0];
const formData = new FormData();
formData.append("image", image);
formData.append("title", this.state.title);
formData.append("text", this.state.editorHtml);
formData.append("category_id", this.state.category_id);
if (this.state.title.length <= 255) {
axios
.post("http://exapmle.com/api/post/store", formData, {
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "multipart/form-data",
Authorization: "Bearer" + this.state.token,
},
})
.then((res) => {
if (res.data.success == true) {
this.setState({ message: "Blog created!" });
setTimeout(() => {
this.setState({ message: "" });
this.props.router.push("/");
}, 5000);
}
});
}
if (this.state.title.length >= 256) {
this.setState({
error_type: "title",
error_message: "Blog name error!",
});
}
};
const apiPostNewsImage = (data) => {
axios
.post("http://exapmle.com/api/image-upload", data, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => console.log(res));
};
const imageHandler = () => {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.click();
input.onchange = async () => {
const file = input.files[0];
const formData = new FormData();
formData.append("image", file);
// Save current cursor state
const range = quill.getSelection(true);
// Insert temporary loading placeholder image
// this.quill.insertEmbed(range.index, "ssurat");
// Move cursor to right side of image (easier to continue typing)
quill.setSelection(range.index + 1);
const res = await axios.post(
"http://exapmle.com/api/image-upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
); // API post, returns image location as string e.g. 'http://www.example.com/images/foo.png'
// Remove placeholder image
quill.deleteText(range.index, 1);
// Insert uploaded image
// this.quill.insertEmbed(range.index, 'image', res.body.image);
quill.insertEmbed(range.index, "image", res.data);
};
};
return (
<Main title="Create blog">
<section className="col-12 col-lg-9 shadow bg-white p-3">
{state.token && (
<form
className="row my-4 col-11 col-lg-8 mx-auto"
onSubmit={(event) => onSubmitForm(event)}
>
<h5 className="title col-12 my-3"> Create blog </h5>
{state.message && (
<div className="alert alert-success">{state.message}</div>
)}
<div className="col-12">
<small className="text-danger p-1"></small>
<div className="input-group p-1">
<div className="custom-file">
<input
type="file"
name="image"
id="image"
className="custom-file-input"
onChange={(event) =>
setState({
...state,
image: event.target.files[0],
})
}
id="image"
required
/>
<label
className="custom-file-label"
data-browse="Select"
htmlFor="image"
aria-describedby="image"
>
Image blog
</label>
</div>
</div>
</div>
<div className="col-12 col-lg-6">
<small className="text-danger p-1 col-12"></small>
<div className="form-label-group p-1">
<input
name="title"
type="text"
id="title"
onChange={(event) =>
setState({
...state,
title: event.target.value,
})
}
className={
state.error_type == "title"
? "form-control border border-danger"
: "form-control"
}
// border border-danger
placeholder="Category name"
autoFocus={true}
required
/>
<label htmlFor="title"> Blog name </label>
{state.error_type == "title" && state.error_message && (
<div className="text-danger">{state.error_message}</div>
)}
</div>
</div>
<div className="col-12 col-lg-6 mt-3">
<div className="form-label-group p-1">
<select name="category_id" className="form-control">
<option value="1"> Category</option>
</select>
</div>
</div>
<div className="col-12">
<ReactQuill
ref={(el) => {
quill = el;
}}
onChange={handleChange}
placeholder={props.placeholder}
modules={{
toolbar: {
container: [
[
{ header: "1" },
{ header: "2" },
{ header: [3, 4, 5, 6] },
{ font: [] },
],
[{ size: [] }],
["bold", "italic", "underline", "strike", "blockquote"],
[{ list: "ordered" }, { list: "bullet" }],
["link", "image", "video"],
["clean"],
["code-block"],
],
handlers: {
image: imageHandler,
},
},
}}
/>
</div>
<button className="btn btn-success mx-auto mt-5">
Create blog
</button>
</form>
)}
{!state.token && (
<div className="alert alert-warning d-flex align-items-center d-flex flex-wrap">
this alert
</div>
)}
</section>
</Main>
);
};
export default withRouter(MyComponent);
this not work
ref={(el) => {
quill = el;
}}
When I connect NEXTJS react-quill, quill does not work.

Related

How to show changes before submit in react

I have a project that make profile cards for users in react. When user create his card I'm tiring to show him how the card looks before he submit and create it.
At this moment the create card work good but I don't know how to show him the card at the same time.
My state update only when he is submit the form.
create component:
function CreatCard() {
const navigate = useNavigate();
const getUserData = JSON.parse(localStorage.getItem("data")).data;
console.log(getUserData.id);
const [bisCard, setBisCard] = useState({
businessName: "",
businessDescription: "",
businessAddress: "",
businessPhone: "",
businessImage: "",
userId: getUserData.id,
});
const handleCreateCard = async (e) => {
e.preventDefault();
const card = { bisCard };
console.log(card.bisCard);
const requestMethods = {
method: "POST",
headers: {
"Content-Type": "application/json",
token: getUserData.token,
},
body: JSON.stringify(card.bisCard),
};
console.log(getUserData.token);
try {
const response = await fetch(
"http://localhost:8000/cards/create",
requestMethods
);
if (response.ok) navigate("/cusomerPage");
else {
console.log(response.json());
}
} catch (err) {
console.log("!!!!", err);
}
};
const handleChangeName = (e) =>
setBisCard({ ...bisCard, businessName: e.target.value });
const handleChangeDescription = (e) =>
setBisCard({ ...bisCard, businessDescription: e.target.value });
const handleChangeAdress = (e) =>
setBisCard({
...bisCard,
businessAddress: e.target.value,
});
const handleChangephone = (e) =>
setBisCard({ ...bisCard, businessPhone: e.target.value });
const handleChangeImg = (e) =>
setBisCard({ ...bisCard, businessImage: e.target.value });
return (
<div>
<div className="creat-form-container">
<CardForm
handleCreateCard={handleCreateCard}
handleChangeName={handleChangeName}
handleChangeDescription={handleChangeDescription}
handleChangeAdress={handleChangeAdress}
handleChangephone={handleChangephone}
handleChangeImg={handleChangeImg}
/>
<div card-container>
<Card card={bisCard}></Card>
</div>
</div>
</div>
);
}
card component:
import DeleteCard from "../deleteCard/DeleteCard";
import "./Card.scss";
const Card = ({ card }) => {
// console.log(card);
return (
<div className="card col my-2 mx-2 ">
<DeleteCard card={card} />
<img
src={card.businessImage}
className="img-size rounded card-img-top "
alt="BusinessImage"
/>
<div className="card-body">
<h5 className="card-title">{card.businessName}</h5>
<p className="card-text">
<b> {card.businessPhone}</b>
</p>
<p className="card-text">{card.businessDescription}</p>
<p className="card-text">
<small className="text-muted">{card.businessAddress}</small>
</p>
</div>
</div>
);
};
export default Card;
thanks for help

Im creating a course marketplace using MERN stack but i get the React-Quill error when I try to open the page of Edit Course

Iam getting this error when I load the page for course edit
Unhandled Runtime Error Error: You are passing the delta object from
the onChange event back as value. You most probably want
editor.getContents() instead. See:
https://github.com/zenoamaro/react-quill#using-deltas
Below is the code of the edit form page CreateCourseForm.js which im importing to the other page [slug].js
import { Badge } from "antd";
import dynamic from "next/dynamic";
const QuillNoSSRWrapper = dynamic(import('react-quill'), {
ssr: false,
loading: () => <p>Loading ...</p>,
});
const CreateCourseForm = ({
handleSubmit,
handleCourseImageUpload,
handleChange,
values,
setValues,
categories,
previewImage,
imageUploadButtonText,
editCategories,
handleCourseImageRemove = (f) => f,
editPage = false,
}) => {
const handleQuillEdit = (value) => {
setValues((prev) => {
return {
...prev,
description: value
}
});
};
const modules = {
toolbar: [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block', 'image'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
// custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'align': [] }],
['clean']
],
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
},
};
return (
<>
{values &&
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Course Name"
name="name"
value={values.name}
onChange={handleChange}
/>
</div>
<div className="form-group">
<QuillNoSSRWrapper theme="snow"
placeholder="Course Description"
modules={modules}
value={values.description || ''}
onChange={handleQuillEdit}/>
</div>
<div className="row form-group">
<label>Course Fee</label>
<div className="col-md-6">
<select
className="form-control"
value={values.paid}
onChange={(v) => setValues({...values, paid: !values.paid})}
>
<option value={false}>Free</option>
<option value={true}>Paid</option>
</select>
</div>
{values.paid &&
<div className="col-md-6">
<input
type="number"
className="form-control"
placeholder="Enter Price in $"
name="price"
value={values.price}
onChange={handleChange}
/>
</div>
}
</div>
<div className="row">
<div className="col-md-8">
<div className="form-group">
<label className="btn btn-outline-secondary btn-block text-left">
{imageUploadButtonText}
<input
type="file"
name="image"
onChange={handleCourseImageUpload}
accept="image/*"
hidden
/>
</label>
</div>
</div>
{previewImage && (
<div className="col-md-4" onClick={handleCourseImageRemove} style={{cursor:'pointer'}}>
<Badge count={"Delete"} style={{color: '#fe4a55'}}>
<img src={previewImage} width="50" alt="image" />
</Badge>
</div>
)}
{editPage && values.image && (
<div className="col-md-2">
<img src={values.image.Location} width="50" alt="image" />
</div>
)}
<p>** If you don't upload any course image then Progyan will update it with a default system image</p>
</div>
<div className="form-group">
<label>Category</label>
<select className="form-control" value={values.category} name="category" onChange={handleChange}>
<option value="none" disabled>Select an Option</option>
{!editPage && categories.map((c) => (
<option value={c.name}>{c.name}</option>
))}
{editPage && editCategories.map((c) => (
<option value={c.name}>{c.name}</option>
))}
</select>
</div>
<button
onClick={handleSubmit}
disabled={values.loading || values.uploading || !values.name || !values.description}>
{values.loading ? "Saving..." : "Save & Continue"}
</button>
</form>
}
</>
);
};
export default CreateCourseForm;
And here is the [slug].js page code
const CourseEdit = () => {
{/*States For Updating Course*/}
const [values, setValues] = useState({
name: "",
description: "",
price: "",
uploading: false,
paid: false,
category: "",
loading: false,
lessons : [],
assessments : [],
});
const [image,setImage] = useState({});
const [previewImage, setPreviewImage] = useState("");
const [imageUploadButtonText, setImageUploadButtonText] = useState('Upload Course Thumbnail');
{/*States For Updating Lesson*/}
const [lessonVisible,setLessonVisible] = useState(false);
const [assessmentVisible,setAssessmentVisible] = useState(false);
const [current, setCurrent] = useState({});
const [updateVideoButtonText, setUpdateVideoButtonText] = useState("Update Lesson Video");
const [progress, setProgress] = useState(0);
const [uploading, setUploading] = useState(false);
const router = useRouter();
const {slug} = router.query;
useEffect(() => {loadCourse();}, [slug]);
const [editCategories, setEditCategories] = useState([]);
useEffect(() => {loadCategories(); }, []);
const loadCategories = async () => {
try {
let { data } = await axios.get("/api/categories");
setEditCategories(data);
} catch (err) {
toast.error(err.response.data);
}
};
{/*Function for load the data from MongoDB to the form*/}
const loadCourse = async () => {
const {data} = await axios.get(`/api/course/${slug}`);
if(data) setValues(data);
if(data && data.image) setImage(data.image);
}
{/*Function for saving all of the data from input form*/}
const handleChange = (e) => {
setValues({...values, [e.target.name]: e.target.value});
};
{/*Function for uploading the course image to AWS S3*/}
const handleCourseImageUpload = (e) => {
let file = e.target.files[0];
setPreviewImage(window.URL.createObjectURL(file));
setImageUploadButtonText(file.name);
setValues({...values, loading: true});
//Resize Image
Resizer.imageFileResizer(file, 750, 500, "JPEG", 90, 0, async (uri) => {
try{
let {data} = await axios.post(`/api/course/upload-image`,{
image: uri,
});
//set Image in the state
setImage(data);
setValues({...values, loading: false});
}catch(err){
setValues({...values, loading: false});
toast.error(err.response.data);
}
});
};
{/*Function for removing the course image from AWS S3*/}
const handleCourseImageRemove = async (e) => {
try{
setValues({...values, loading: true});
const res = await axios.post(`/api/course/remove-image`, {image});
setImage({});
setPreviewImage("");
setImageUploadButtonText('Upload Course Thumbnail');
setValues({...values, loading: false});
}catch(err){
setValues({...values, loading: false});
toast.error(err.response.data);
}
}
{/*Function for updating the course to MongoDB*/}
const handleSubmit = async (e) => {
e.preventDefault();
try{
if(!values.paid){ values.price=0; }
const {data} = await axios.put(`/api/course/${slug}`, {
...values,
image,
});
toast.success("Course Updated Successfully..!!");
}catch(err){
toast.error(err.response.data);
}
};
{/*Function for updating the lesson video to AWS S3*/}
const handleVideoUpdate = async (e) => {
//Remove Previous Video
if(current.video && current.video.Location){
const res = await axios.post(`/api/course/video-remove/${values.instructor._id}`, current.video);
toast.success(res);
}
//Upload
const file = e.target.files[0];
setUpdateVideoButtonText(file.name);
setUploading(true);
//Send Video as form data
const videoData = new FormData();
videoData.append('video',file);
videoData.append('courseId',values._id);
//Save progress bar and send video form data to backend
const {data} = await axios.post(
`/api/course/video-upload/${values.instructor._id}/${values.slug}`,
videoData,
{
onUploadProgress: (e) => setProgress(Math.round((100 * e.loaded) / e.total)),
}
);
setCurrent({...current, video: data});
setUploading(false);
};
{/*Function for dragging the lesson sequence*/}
const handleLessonDrag = (e, index) => {
e.dataTransfer.setData("itemIndex", index);
};
{/*Function for dropping the lesson sequence*/}
const handleLessonDrop = async (e, index) => {
const movingItemIndex = e.dataTransfer.getData("itemIndex");
const targetItemIndex = index;
let allLessons = values.lessons;
let movingItem = allLessons[movingItemIndex]; //Clicked or Dragged Item to Reorder
allLessons.splice(movingItemIndex, 1); //Remove 1 item from the given index
allLessons.splice(targetItemIndex, 0, movingItem); //Push item after target item index
setValues({...values, lessons: [...allLessons]});
//Save the new lessons order in MongoDB
const {data} = await axios.put(`/api/course/${slug}`,{...values, image});
toast.success("Lesson Rearrange Successfully");
};
{/*Function for deleting the lesson from the course & MongoDB*/}
const handleDeleteLesson = async (index) => {
Swal.fire({
title: 'Are you sure?',
text: "Do You Want To Delete This Lesson..??",
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes, Delete It.!'
}).then(async (result) => {
if (result.isConfirmed) {
let allLessons = values.lessons;
const removed = allLessons.splice(index, 1);
setValues({...values, lessons: allLessons});
const {data} = await axios.put(`/api/course/${slug}/${removed[0]._id}`);
toast.success("Lesson Deleted Successfully..!!!");
}
});
};
{/*Function for updating the lesson to MongoDB*/}
const handleUpdateLesson = async (e) => {
e.preventDefault();
const {data}= await axios.put(`/api/course/lesson/${slug}/${current._id}`, current);
setUpdateVideoButtonText("Update Lesson Video");
setLessonVisible(false);
//Update UI
if(data.ok){
let arr = values.lessons;
const index = arr.findIndex((el) => el._id === current._id);
arr[index] = current;
setValues({...values, lessons:arr});
toast.success("Lesson Updated Successfully..!");
}
};
{/*Function for dragging the assessment sequence*/}
const handleAssessmentDrag = (e, index) => {
e.dataTransfer.setData("itemIndex", index);
};
{/*Function for dropping the assessment sequence*/}
const handleAssessmentDrop = async (e, index) => {
const movingItemIndex = e.dataTransfer.getData("itemIndex");
const targetItemIndex = index;
let allAssessments = values.assessments;
let movingItem = allAssessments[movingItemIndex]; //Clicked or Dragged Item to Reorder
allAssessments.splice(movingItemIndex, 1); //Remove 1 item from the given index
allAssessments.splice(targetItemIndex, 0, movingItem); //Push item after target item index
setValues({...values, assessments: [...allAssessments]});
//Save the new assessment order in MongoDB
const {data} = await axios.put(`/api/course/${slug}`,{...values, image});
toast.success("Assessment Rearrange Successfully");
};
{/*Function for deleting the assessment from the course & MongoDB*/}
const handleDeleteAssessment = async (index) => {
Swal.fire({
title: 'Are you sure?',
text: "Do You Want To Delete This Assessment..??",
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes, Delete It.!'
}).then(async (result) => {
if (result.isConfirmed) {
let allAssessments = values.assessments;
const removed = allAssessments.splice(index, 1);
setValues({...values, assessments: allAssessments});
const {data} = await axios.put(`/api/course/assessment/${slug}/${removed[0]._id}`);
toast.success("Assessment Deleted Successfully..!!!");
}
});
};
{/*Function for updating the assessment to MongoDB*/}
const handleUpdateAssessment = async (e) => {
e.preventDefault();
const {data}= await axios.put(`/api/course/assessment/${slug}/${current._id}`, current);
setAssessmentVisible(false);
//Update UI
if(data.ok){
let arr = values.assessments;
const index = arr.findIndex((el) => el._id === current._id);
arr[index] = current;
setValues({...values, assessments:arr});
toast.success("Assessment Updated Successfully..!");
}
};
return (
<InstructorRoute>
<React.Fragment>
<PageBanner
pageTitle="Edit Course"
homePageUrl="/instructor"
homePageText="Dashboard"
activePageText="Edit Course"
/>
<div className="footer-area pt-100 pb-70">
<div className="container">
<div className="login-form">
<CreateCourseForm
handleSubmit={handleSubmit}
handleCourseImageUpload={handleCourseImageUpload}
handleChange={handleChange}
values={values}
setValues={setValues}
editCategories={editCategories}
previewImage={previewImage}
imageUploadButtonText={imageUploadButtonText}
handleCourseImageRemove={handleCourseImageRemove}
editPage={true}
/>
</div>
</div>
</div>
{values.lessons && values.lessons.length > 0 &&
<div className="about-area bg-fef8ef ptb-100">
<div className="container">
<div className="section-title">
<h5>Drag & Drop the Lessons to Change The Sequence</h5>
</div>
<List
onDragOver={(e) => e.preventDefault()}
dataSource={values && values.lessons}
renderItem={(item, index) => (
<Item
draggable
onDragStart={(e) => handleLessonDrag(e, index)}
onDrop={(e) => handleLessonDrop(e, index)}>
<div className="single-courses-item">
<div className="courses-content d-flex justify-content-between">
<h3>{index+1}) {item.title.length > 10 ? item.title.substring(0,10)+"...": item.title}</h3>
<div className="float-right">
<EditOutlined className="complementary-btn mx-5" onClick={() => {
setLessonVisible(true);
setCurrent(item);
}}/>
<DeleteOutlined
className="text-danger"
onClick={() => handleDeleteLesson(index)}/>
</div>
</div>
</div>
</Item>
)}>
</List>
</div>
<div className="shape1"><img src="/images/shape1.png" alt="image" /></div>
<div className="shape2"><img src="/images/shape2.png" alt="image" /></div>
<div className="shape3"><img src="/images/shape3.png" alt="image" /></div>
<div className="shape4"><img src="/images/shape4.png" alt="image" /></div>
</div>
}
{values.assessments && values.assessments.length > 0 &&
<div className="main-banner-wrapper ptb-100">
<div className="container">
<div className="section-title">
<h5>Drag & Drop the Assessment to Change The Sequence</h5>
</div>
<List
onDragOver={(e) => e.preventDefault()}
dataSource={values && values.assessments}
renderItem={(item, index) => (
<Item
draggable
onDragStart={(e) => handleAssessmentDrag(e, index)}
onDrop={(e) => handleAssessmentDrop(e, index)}>
<div className="single-courses-item">
<div className="courses-content d-flex justify-content-between">
<h3>{index+1}) {item.question.length > 10 ? item.question.substring(0,10)+"...": item.question}</h3>
<div className="float-right">
<EditOutlined className="complementary-btn mx-5" onClick={() => {
setAssessmentVisible(true);
setCurrent(item);
}}/>
<DeleteOutlined
className="text-danger"
onClick={() => handleDeleteAssessment(index)}/>
</div>
</div>
</div>
</Item>
)}>
</List>
</div>
<div class="banner-shape14"><img src="/images/banner-shape15.png" alt="image"/></div>
<div class="banner-shape15"><img src="/images/banner-shape16.png" alt="image"/></div>
<div class="banner-shape16"><img src="/images/banner-shape17.png" alt="image"/></div>
<div class="banner-shape17"><img src="/images/banner-shape18.png" alt="image"/></div>
<div class="banner-shape18"><img src="/images/banner-shape19.png" alt="image"/></div>
</div>
}
<div className="newsletter-modal" style={{display: lessonVisible?"block":"none"}}>
<div className="newsletter-modal-content">
<a className="close-btn" onClick={() => setLessonVisible(false)}>Close</a>
<UpdateLessonForm
current={current}
setCurrent={setCurrent}
handleVideoUpdate={handleVideoUpdate}
handleUpdateLesson={handleUpdateLesson}
updateVideoButtonText={updateVideoButtonText}
progress={progress}
uploading={uploading}
/>
</div>
</div>
<div className="newsletter-modal" style={{display: assessmentVisible?"block":"none"}}>
<div className="newsletter-modal-content">
<a className="close-btn" onClick={() => setAssessmentVisible(false)}>Close</a>
<UpdateAssessmentForm
current={current}
setCurrent={setCurrent}
handleUpdateAssessment={handleUpdateAssessment}
/>
</div>
</div>
<div className="lines">
<div className="line"></div>
<div className="line"></div>
<div className="line"></div>
</div>
</React.Fragment>
</InstructorRoute>
);
};
export default CourseEdit;

How do I pass the id from the addNewFriendClick to my onClickUpdate?

I have a friend form that has a button to add friend via ajax call (addNewFriendClick). Once added it should output the id and then using that id the same button (onClickUpdate) should allow to update by grabbing that id.
After adding and clicking a second time to update the friend I get the error below in my console.
The website below should have the /id as the url ending endpoint but i am getting
"[object%20Object]"
PUT https://api.remotebootcamp.dev/api/friends/[object%20Object] 404 (Not Found)
Below is my Routes
<Route path="/friends/*" element={<AddFriend></AddFriend>}>
<Route path=":personId" element={<AddFriend />}></Route>
<Route path="new" element={<AddFriend />}></Route>
</Route>
import React, { useState, useEffect } from "react";
import * as friendService from "../../services/friendService";
import toastr from "toastr";
import { useParams, useNavigate, useLocation } from "react-router-dom";
function AddFriend() {
const [userFormData, setUserFormData] = useState({
title: "",
bio: "",
summary: "",
headline: "",
slug: "",
statusId: "",
primaryImage: "",
});
// useEffect to grab url
const navigate = useNavigate();
const { state } = useLocation();
const friendId = useParams();
const [peepId, setPeepId] = useState(friendId);
console.log({ userFormData, peepId, state }, "param and navigate");
useEffect(() => {
console.log("useEffect firing");
setPeepId(friendId);
if (state) {
setUserFormData((prevState) => {
console.log(state);
return { ...prevState, ...state.payload };
});
}
}, [friendId, state]);
const onFormFieldChange = (event) => {
const target = event.target;
const value = target.value;
console.log("VALUE ->", value);
const name = target.name;
console.log("NAME ->", name);
setUserFormData((prevState) => {
console.log("updater onChange");
const updatedFormData = {
...prevState,
};
updatedFormData[name] = value;
return updatedFormData;
});
};
useEffect(() => {
console.log("useEffect firing");
setPeepId(friendId);
if (state) {
setUserFormData((prevState) => {
console.log(state);
return { ...prevState, ...state.payload };
});
}
}, [friendId, state]);
const addNewFriendClick = (event) => {
event.preventDefault();
console.log(userFormData, "inside addNewFriendClick")
console.log("on Click", { syntheticEvent: event });
friendService.addFriend(userFormData).then(onSuccessAdd).catch(onErrAdd);
};
const onSuccessAdd = (response) => {
console.log(response, "onSuccessAdd response");
// console.log(response.data.item, "onSuccessAdd response.data.item");
setNewFriendInformation(response);
console.log(response,"onSuccessAdd after setNewFriend" )
friendService.getFriendById(response).then(onSuccessGet).catch(onErrorGet);
toastr.success("Congratulations! You have successfully added a friend!");
};
const onErrAdd = (err) => {
console.log("ping err", err);
// swal("Error Registering");
toastr.error(
"Error adding a new friend. Please check if all fields are correct"
);
};
const onClickUpdate = (event) => {
console.log(userFormData, "userFormData inside click Edit");
event.preventDefault();
friendService
.updateFriend(userFormData)
.then(onSuccessUpdate)
.catch(onErrorUpdate);
};
const onSuccessUpdate = (response) => {
console.log(response);
toastr.success("Congratulations! You have successfully updated a friend!");
navigate("/friends");
};
const onErrorUpdate = (error) => {
console.log(error, "inside error update");
toastr.error(
"Error updating friend. Please check all fields are correct and that user being updated is valid"
);
};
const setNewFriendInformation = (id) => {
setUserFormData((prevState) => {
let newState = { ...prevState };
newState.id = id;
return newState;
});
};
const onSuccessGet = (response) => {
console.log(response);
navigate();
};
const onErrorGet = (error) => {
console.log(error);
console.log("inside getById error form");
};
// const updateFriend()
return (
<React.Fragment>
<h1 className="container">Add New</h1>
<hr />
<main role="main">
<div className="container col-6 mt-5 fs-2">
<div className="row">
<div className="col-md-5">
<form>
<div className="mb-3">
<label htmlFor="title" className="form-label">
Title
</label>
<input
type="text"
className="form-control form-control-lg"
id="title"
name="title"
placeholder="Please The Enter Title"
onChange={onFormFieldChange}
value={userFormData.title}
/>
</div>
<div className="mb-3">
<label htmlFor="bio" className="form-label">
Bio
</label>
<input
type="text"
className="form-control form-control-lg"
id="bio"
name="bio"
placeholder="Please Enter The Bio"
value={userFormData.bio}
onChange={onFormFieldChange}
/>
</div>
<div className="mb-3">
<label htmlFor="summary" className="form-label">
Summary
</label>
<input
type="text"
className="form-control form-control-lg"
id="summary"
name="summary"
placeholder="Please Enter The Summary"
onChange={onFormFieldChange}
value={userFormData.summary}
/>
</div>
<div className="mb-3">
<label htmlFor="headline" className="form-label">
Headline
</label>
<input
type="text"
className="form-control form-control-lg"
id="headline"
name="headline"
placeholder="Please Enter The Headline"
onChange={onFormFieldChange}
value={userFormData.headline}
/>
</div>
<div className="mb-3">
<label htmlFor="slug" className="form-label">
Slug
</label>
<input
type="text"
className="form-control form-control-lg"
id="slug"
name="slug"
placeholder="Please The Slug"
onChange={onFormFieldChange}
value={userFormData.slug}
/>
</div>
<div className="mb-3">
<label htmlFor="statusId" className="form-label">
Status Id
</label>
<select
type="select"
className="form-control"
id="statusId"
name="statusId"
placeholder="Please Enter Status ID"
onChange={onFormFieldChange}
value={userFormData.statusId}
>
<option>Default</option>
<option value="Active">Active</option>
<option value="NotSet">NotSet</option>
<option value="Deleted">Deleted</option>
<option value="Flagged">Flagged</option>
</select>
</div>
<div className="mb-3">
<label htmlFor="primaryImage" className="form-label">
Primary Image Url
</label>
<input
type="text"
className="form-control form-control-lg"
id="primaryImage"
name="primaryImage"
placeholder="Please Enter The Primary Image"
onChange={onFormFieldChange}
value={userFormData.primaryImage}
/>
</div>
{userFormData.id ? (
<button
onClick={onClickUpdate}
type="sumbit"
className="btn btn-primary"
>
Update Friend
</button>
) : (
<button
onClick={addNewFriendClick}
type="sumbit"
className="btn btn-primary"
>
Add Friend
</button>
)}
</form>
</div>
</div>
</div>
<div className="col-md-5">
<h5>Output</h5>
<pre>
<code>{JSON.stringify(userFormData, undefined, 2)}</code>
</pre>
</div>
</main>
</React.Fragment>
);
}
export default AddFriend;
import axios from "axios";
import * as helper from "./serviceHelper";
let getFriend = () => {
const config = {
method: "GET",
url: "https://api.remotebootcamp.dev/api/friends?pageIndex=0&pageSize=10",
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config).then(helper.onGlobalSuccess);
//we use data as the param for success handler
};
let addFriend = (payload) => {
const config = {
method: "POST",
url: "https://api.remotebootcamp.dev/api/friends",
data: payload,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config).then(response => {
console.log(response, "inside service addfriend return")
return response.data.item;
});
}
let updateFriend = (id, payload) => {
console.log(id, payload, "from updateFriendservice");
const config = {
method: "PUT",
data: (id, payload),
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config);
};
let deleteFriend = (id) => {
console.log(id);
const config = {
method: "DELETE",
// data: id,
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config);
};
let getFriendById = (id, payload) =>{
console.log(id, payload, "inside getFriend friedService")
const config = {
method: "PUT",
data: (id, payload),
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
}
return axios(config);
}
export { getFriend, addFriend, deleteFriend, updateFriend, getFriendById };
Maybe you should get friendId as following
const { personId: friendId } = useParams();
Also you need to send two prams to friendService.updateFriend() but sent only one param.

I am getting the following error while creating a signin page using react : Error: Maximum update depth exceeded

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
I am getting the above error but can't find any infinite loops in my code. please help with it
import React, { useState } from "react";
import Base from "../core/Base";
import { Redirect } from "react-router-dom";
import {
signin,
authenticate,
isAuthenticated,
} from "../auth/helper/authapicalls";
const Signin = () => {
const [values, setValues] = useState({
email: "",
password: "",
error: "",
loading: false,
didRedirect: false,
});
const { email, password, error, loading, didRedirect } = values;
var user = isAuthenticated();
const handleChange = (name) => (event) => {
setValues({ ...values, error: false, [name]: event.target.value });
};
const onSubmit = (event) => {
event.preventDefault();
setValues({ ...values, error: false, loading: true });
signin({ email, password })
.then((data) => {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
authenticate(data, () => {
setValues({ ...values, didRedirect: true });
});
}
})
.catch(console.log("Signin request failed"));
};
const performRedirect = () => {
if (didRedirect) {
if (user) {
return <Redirect to="/admin/dashboard" />;
}
}
};
const loadingMesage = () => {
return (
loading && (
<div className="alert alert-warning">
<h3>Loading...</h3>
</div>
)
);
};
const errorMessage = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
</div>
</div>
);
};
const signinForm = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<form>
<div className="form-group">
<label className="text-dark">Email</label>
<input
onChange={handleChange("email")}
value={email}
className="form-control"
type="email"
/>
</div>
<div className="form-group">
<label className="text-dark">Password</label>
<input
onChange={handleChange("password")}
value={password}
className="form-control"
type="password"
/>
</div>
<button onClick={onSubmit} className="btn btn-datk btn-block">
Sign In
</button>
</form>
</div>
</div>
);
};
return (
<Base>
<div className="text-dark text-center mb-5 p-4">
<h3>Sign in</h3>
</div>
{loadingMesage()}
{errorMessage()}
{signinForm()}
{performRedirect()}
</Base>
);
};
export default Signin;
It's your handleChange event handler. You're calling it as soon as component renders. But you have to bind it. I did the same using arrow functions.
import React, { useState } from "react";
import Base from "../core/Base";
import { Redirect } from "react-router-dom";
import {
signin,
authenticate,
isAuthenticated,
} from "../auth/helper/authapicalls";
const Signin = () => {
const [values, setValues] = useState({
email: "",
password: "",
error: "",
loading: false,
didRedirect: false,
});
const { email, password, error, loading, didRedirect } = values;
var user = isAuthenticated();
const handleChange = (name) => (event) => {
setValues({ ...values, error: false, [name]: event.target.value });
};
const onSubmit = (event) => {
event.preventDefault();
setValues({ ...values, error: false, loading: true });
signin({ email, password })
.then((data) => {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
authenticate(data, () => {
setValues({ ...values, didRedirect: true });
});
}
})
.catch(console.log("Signin request failed"));
};
const performRedirect = () => {
if (didRedirect) {
if (user) {
return <Redirect to="/admin/dashboard" />;
}
}
};
const loadingMesage = () => {
return (
loading && (
<div className="alert alert-warning">
<h3>Loading...</h3>
</div>
)
);
};
const errorMessage = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
</div>
</div>
);
};
const signinForm = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<form>
<div className="form-group">
<label className="text-dark">Email</label>
<input
onChange={()=>handleChange("email")}
value={email}
className="form-control"
type="email"
/>
</div>
<div className="form-group">
<label className="text-dark">Password</label>
<input
onChange={()=>handleChange("password")}
value={password}
className="form-control"
type="password"
/>
</div>
<button onClick={onSubmit} className="btn btn-datk btn-block">
Sign In
</button>
</form>
</div>
</div>
);
};
return (
<Base>
<div className="text-dark text-center mb-5 p-4">
<h3>Sign in</h3>
</div>
{loadingMesage()}
{errorMessage()}
{signinForm()}
{performRedirect()}
</Base>
);
};
export default Signin;

Once i clicked first time then it should run with the values i change in the fields every 10 second and submit automatically

Basically what i want to do is run this update function with the values i give. after i submit it for the first time it should run automatically with the values i change. after the first submit all i want to do is change the values and wait 10 seconds and let the program to automatically run.
How to run it automatically after the first submit?
import React, { useState, useEffect } from 'react';
import { API } from './config';
const UpdateAlarm = ({ match }) => {
const [values, setValues] = useState({
sensorId: "",
smoke: "",
co2: "",
error: false,
success: false
});
const {
sensorId,
smoke,
co2,
error,
success
} = values;
const updateSensor = (sensorId, smoke, co2) => {
return fetch(`${API}/setSensorLevels`, {
method: "PUT",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
sensorId: sensorId,
smoke: smoke,
co2: co2
})
}).then(response => {
return response.json();
})
.catch(err => console.log(err));
};
const init = (sensorId, smoke, co2) => {
setValues({
...values,
sensorId: sensorId,
smoke: smoke,
co2: co2,
})
};
useEffect(() => {
init(match.params.sensorId, match.params.smoke, match.params.co2);
}, []);
const handleChange = name => event => {
const value = event.target.value;
setValues({ ...values, [name]: value });
};
const clickSubmit = event => {
event.preventDefault();
setValues({ ...values, error: "" });
if (smoke > 10 || smoke < 0) {
setValues({ ...values, error: "Smoke level must be greater than 0 or less than 10" });
}
else if (co2 > 10 || co2 < 0) {
setValues({ ...values, error: "CO2 level must be greater than 0 or less than 10" });
}
else {
updateSensor(sensorId, smoke, co2).then(data => {
if (data.error) {
setValues({ ...values, error: data.error, success: false });
} else {
setValues({
...values,
sensorId: sensorId,
smoke: smoke,
co2: co2,
error: false,
});
setValues({ ...values, error: false, success: "Sensor Values Updated!" });
setTimeout(() => {
setValues({ ...values, error: false, success: false });
}, 2000);
}
});
}
};
const newPostForm = () => (
<form className="mb-3" onSubmit={clickSubmit}>
<h2>Update Sensor Status</h2> <br />
<div className="form-group">
<label className="text-muted">Sensor Status</label>
<input
type="number"
className="form-control"
value={sensorId}
disabled={true} />
</div>
<div className="form-group">
<label className="text-muted">Sensor Status</label>
<input
onChange={handleChange("smoke")}
type="number"
className="form-control"
min="0" max="10"
value={smoke} />
</div>
<div className="form-group">
<label className="text-muted">Sensor Status</label>
<input
onChange={handleChange("co2")}
type="number"
className="form-control"
min="0" max="10"
value={co2} />
</div>
<button className="btn btn-dark">Update Sensor</button>
</form>
);
const showError = () => (
<div className="alert alert-danger" style={{ display: error ? '' : 'none' }}>
{error}
</div>
);
const showSuccess = () => (
<div className="alert alert-success" style={{ display: success ? '' : 'none' }}>
{success}
</div>
);
return (
<div className="row">
<div className="col-md-8 offset-md-2">
<div className="container-fluid">
<div className="jumbotron">
{showSuccess()}
{showError()}
{newPostForm()}
</div>
</div>
</div>
</div>
);
}
export default UpdateAlarm;

Categories

Resources