Unable to make a PATCH request using radio buttons in ReactJS - reactjs

I am trying to add in a list of tasks and want to change them to either "Complete" or "Not Complete" using radio buttons and then updating it to send a PATCH request to the data to update. When I press update nothing changes on the data.
This is the code I have for this page:
`
function ProjectDetails() {
const [WaxProcedure, setWaxProcedure] = useState("");
const { id } = useParams();
const {
data: project,
error,
isPending,
} = useFetch(`http://localhost:8000/ProjectsData/${id}`);
const history = useNavigate();
const handleClickDelete = () => {
fetch(`http://localhost:8000/ProjectsData/${id}`, {
method: "DELETE",
}).then(() => {
history("/");
});
};
const handleUpdate = () => {
fetch(`http://localhost:8000/ProjectsData/${id}`, {
method: "PATCH",
headers: {
"Content-type": "application/json",
body: JSON.stringify(project),
},
}).then((response) => {
response.json();
});
};
return (
<div className="project-details">
{isPending && <div>Loading...</div>}
{error && <div>{error}</div>}
{project && (
<article>
<h1>{project.Customer}</h1>
<h2>
{project.Part} {project.Description}
</h2>
<h2>{project.Tool}</h2>
<div>Project Status: {project.Stage}</div>
<p>Lead engineer: {project.Engineer}</p>
<div className="procedure-list">
<form onSubmit={handleUpdate}>
Wax: <p>{WaxProcedure}</p>
<input
type="radio"
name="waxprocedure"
value="Not Complete"
required
onChange={(e) => setWaxProcedure(e.target.value)}
/>
Not Complete
<input
type="radio"
name="waxprocedure"
value="Complete"
required
onChange={(e) => setWaxProcedure(e.target.value)}
/>
Complete
<button type="submit" onClick={handleUpdate}>
Update
</button>
</form>
</div>
<button type="submit" onClick={handleClickDelete}>
Delete
</button>
</article>
)}
</div>
);
}
`
Any ideas why the data won't update? I am new to this and spent a long time trying to find an answer.
I have tried the patch request on Postman and this worked too, so nothing wrong with the request.

remove "onsubmit" from form tag and remove type="submit" from both buttons and pass "project" parameter to handleupdate method

Related

Leadspedia Form Submission does not work with onSubmit

I have a form in React that I'm trying to submit to Leadspedia, but I'm seeing strange behavior. The instructions from Leadspedia API shows an example of using the method and action options to send the form. I'd like to use the onSubmit event handler to have more control of the form, but for some reason that returns with an error. Using their example submits correctly. Here is my code:
const postData = async (url = '', data = {}) => {
const response = await fetch(url, {
method: 'POST',
body: JSON.stringify(data),
});
return response.json();
}
const handleSubmit = async (e) => {
e.preventDefault();
const url = "*leadspedia end point*";
const data = formValues;
postData(url, data)
.then((data) => {
console.log(data)
})
.catch(error => {
console.log(error)
})
resetForm(
Here is my form:
<form
style={{ width: '100%'}}
onSubmit={handleSubmit}
id="lp_form"
action="*leadspedia endpoint*"
method="post"
>
<div>
{formSections?.[formStep]?.fields?.map((field, index) => (
renderInput(field, index)
))}
{Object.keys(formValues).map((key, index) => (
<input key={index} type="hidden" name={key} value={formValues[key]} />
))}
<input type="hidden" id="lp_offer_id" name="lp_offer_id" value={offerId} />
<input type="hidden" id="lp_campaign_id" name="lp_campaign_id" value={campaignId} />
<input type="hidden" id="lp_campaign_key" name="lp_campaign_key" value={campaignKey} />
</div>
<div>
{formStep === 9 && (
<Button type="submit" variant="primary">
Submit
</Button>
)}
</div>
</form>
Submitting without the handleSubmit function works perfectly fine. However, submitting the form with the handleSubmit function returns a response that says Invalid campaign key or id. I've checked the values multiple times and it's the correct key and id. Am I missing something the handleSubmit function that would cause this error?

How to not give user access to the login page when they are already logged in?

https://pastebin.com/mXgqRP4j
I am trying to implement that when a user is logged in, the user has no access to the login page. To do that I have put an if condition at the end that if the user is authenticated, the user will be redirected to the dashboard even when they input the path to the login component. But whats happening is that when I input the link to the login page (I have routes set up), the login page shows up for a split second and then disappears and then the dashboard appears. What should have happened was that the user shouldve been redirected directly to the dashboard. Please guide me!
import { useEffect, useState } from "react"
import Admin from "../../pages/Admin"
import { Navigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function AdminLogin() {
const navigate = useNavigate()
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [csrf, setCsrf] = useState('')
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
function getCsrf(){
fetch("http://localhost:8000/csrf/", {
credentials: "include",
})
.then((res) => {
let csrfToken = res.headers.get("X-CSRFToken");
setCsrf({csrf: csrfToken});
})
.catch((err) => {
console.log(err);
})
}
const login = (event) => {
event.preventDefault();
fetch("http://localhost:8000/login/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrf.csrf,
},
credentials: "include",
body: JSON.stringify({username: username, password: password}),
})
.then(isResponseOk)
.then((data) => {
console.log(data);
setIsAuthenticated(true)
localStorage.setItem("authenticated", true);
setUsername('')
setPassword('')
// this.setState({isAuthenticated: true, username: "", password: ""});
})
.catch((err) => {
console.log('inside login catch')
console.log(csrf.csrf, 'catch')
console.log(err);
});
}
const isResponseOk = (response) =>{
if (response.status >= 200 && response.status <= 299) {
return response.json();
} else {
console.log(response)
throw Error(response.statusText);
}
}
useEffect(() => {
//getSessions
fetch("http://localhost:8000/session/", {
credentials: "include",
})
.then((res) => res.json())
.then((data) => {
// console.log(data);
if (data.isAuthenticated) {
setIsAuthenticated(true)
console.log(data)
} else {
setIsAuthenticated(false)
console.log(data)
getCsrf()
}})
.catch((err) => {
console.log(err);
});
}, [])
console.log(csrf);
console.log(counter)
const handleUsername = (e) => {
setUsername(e.target.value)
}
const handlePassword = (e) => {
setPassword(e.target.value)
}
const loginScreen = (
<div className="login-box m-auto">
<div className="card">
<div className="card-body login-card-body">
<p className="login-box-msg">Sign in to start your session</p>
<form method="post" onSubmit={login}>
<div className="input-group mb-3">
<input required type="text" value={username} onChange={handleUsername} className="form-control" placeholder="Username" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-envelope" />
</div>
</div>
</div>
<div className="input-group mb-3">
<input required type="password" value={password} onChange={handlePassword} className="form-control" placeholder="Password" />
<div className="input-group-append">
<div className="input-group-text">
<span className="fas fa-lock" />
</div>
</div>
</div>
<div className="row">
<div className="col-4">
<button type="submit" className="btn btn-primary btn-block">Sign In</button>
</div>
</div>
</form>
</div>
</div>
</div>)
if(isAuthenticated)
{
return <Navigate replace to="/admin/dashboard" />;
}
else{
return loginScreen
}
}
You can create isLoading state alongside isAuthenticated state and initialize it with true and show the loading screen until checking authentication is finished and set isLoading to false. After that you can show the login screen only if isLoading is false and isAuthentcated is also false.
If it's okay to use Redux so I suggest using Redux-Persist and make it rehydrate the auth part so you will not face this issue.

Why isnt my pic getting displayed after using Active Storage?

I am trying to implement active storage .And have been following along with this article .Its a very very short article https://dev.to/jblengino510/uploading-files-in-a-react-rails-app-using-active-storage-201c.The backend has been set correctly as instructed...The only problem is in the front end..I am not able to write my React project code in a way thats similar to this project and hence im lacking a correct code.
Here is my Project code
The add review form card
function AddReviewForm({user,handleAddReviews}){
const params = useParams();
const[img,setImg]=useState("");
const[r,setR]=useState("");
const[imgData,setimgData]=useState("");
const newReview = {
img,
r,
imgData,
restaurant_id: params.id,
user_id: user.id,
};
const configObj = {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(newReview),
};
function handleReviewSubmit(event) {
event.preventDefault();
fetch(`/reviews`, configObj)
.then((r) => r.json())
.then((review)=>{
handleAddReviews(review);
setR('')
setImg('')
setimgData('')
}
);
}
return (
<>
<h1>Add review form</h1>
<form onSubmit={handleReviewSubmit}>
<div>
<input type="file"
name="picture"
accept="image/png, image/gif, image/jpeg"
id="picture"
onChange={(e)=>setimgData(e.target.files[0])} />
</div>
<div>
<label htmlFor="r" >Review</label>
<input type="text" name="r" value={r} onChange={(e) => setR(e.target.value)} placeholder="review" />
</div>
<input type="submit" />
</form>
</>
)
}
export default AddReviewForm;
And the displayed ReviewCard.js
import { useParams } from "react-router-dom";
function ReviewCard({review,user,handleDelete}){
const{id,img,r,picture,user:reviewuser}=review
function handleDeleteClick() {
fetch(`/reviews/${review.id}`, {
method: "DELETE",
})
handleDelete(review.id)
}
return(
<>
<img src={img}/>
<img src={picture} />
<p></p>
<p>{r}</p>
<h6>By {review.user.name}</h6>
{user.id===reviewuser.id&&<button onClick={handleDeleteClick} >Delete</button>}
</>
)
}
export default ReviewCard;
Pls help me out and lemme know what changed I can do so that my picture gets displayeddd

How to get progressbar when file upload to browser

How to get file uploading percentage when file uploading from client file system to client's browser.
I have the simplest form. I need to get file uploading percentage and show it to user when he upload file.
export default function App() {
const handleSubmit = (e) => {
e.preventDefault();
console.log("submit");
};
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input type="file" />
<input type="submit" value="click to submit" />
</form>
</div>
);
}
Demo
here is small example, with react bootsttrap you can try,
you have to import,
import { Container, Row, Col, Form, Button, ProgressBar } from "react-bootstrap"
your javascript logic will be like this, ProgressBar needs % percentage value, you can calculate that,
const [selectedFiles, setSelectedFiles] = useState()
const [progress, setProgress] = useState()
const handleSubmit = e => {
e.preventDefault() //prevent the form from submitting
let formData = new FormData()
formData.append("file", selectedFiles[0])
const axios = axios.create({
baseURL: "http://localhost:8080/",
})
axios.post("/upload_file", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress: data => {
//Set the progress value to show the progress bar
setProgress(Math.round((100 * data.loaded) / data.total))
},
})
}
here is component return will look like,
<Form
action="http://localhost:8081/upload_file"
method="post"
encType="multipart/form-data"
onSubmit={handleSubmit}
>
<Form.Group>
<Form.File
label="Select a File"
onChange={e => {
setSelectedFiles(e.target.files)
}}
/>
</Form.Group>
<Form.Group>
<Button variant="info" type="submit">
Upload A File
</Button>
</Form.Group>
{progress && <ProgressBar now={progress} label={`${progress}%`} />}
</Form>

Issue to submit CSV file to DB via POST Axios & React-Final-Form

I need to save the content of a CSV into a database table by using React-Final-Form and Axios.
I have tried to create a simple HTML without using Final-Form or Axios and the submission to the DB works fine.
The problem is when I try to pass the content of the CSV to a function which will handle the POST call.
See code below:
import React, { Fragment } from "react";
import { Form, Field } from "react-final-form";
import createDecorators from "final-form-focus";
const handleSubmitOnClick = file => {
const url = 'http://localhost:3000/api/v1/invitations/upload';
const data = new FormData();
data.append('file', new File([file], { type: 'text/csv' }));
return axios.post(url, data, {
headers: {
'content-type': 'multipart/form-data'
}
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
const JoinTesting = () =>
<Fragment>
<h1>Join Testing Page</h1>
<Form
onSubmit={handleSubmitOnClick}
decorators={[focusOnError]}
>
{
({
handleSubmit,
values,
submitting,
}) => (
<form onSubmit={handleSubmit} encType="multipart/form-data">
<Field
name='invitation[file]'
placeholder='Upload csv file'
validate={required}
>
{({ input, meta, placeholder }) => (
<div className={meta.active ? 'active' : ''}>
<label>{placeholder}</label>
<input {...input}
type='file'
placeholder={placeholder}
className="join-field-input"
/>
{meta.error && meta.touched && <span className="invalid">{meta.error}</span>}
{meta.valid && meta.dirty && <span className="valid">Great!</span>}
</div>
)}
</Field>
<button
type="submit"
className="join-button"
disabled={submitting}
>
Submit
</button>
<pre>{JSON.stringify(values, 0, 2)}</pre>
</form>
)}
</Form>
</Fragment>
export default JoinTesting;
If I remove ALL the above and I just use this HTML within my JoinTesting component, it works fine but I can't handle the errors (if any)
<form action="http://localhost:3000/api/v1/invitations/upload" method="post" encType="multipart/form-data">
Select CSV to upload:
<input type="file" name="invitation[file]" id="fileToUpload" />
<br></br>
<input type="submit" value="Upload CSV" name="submit" />
</form>
PLEASE NOTE: The CSV file has only a simple 1 column with a sequence of email addresses.
This is what the POST request expects:
Headers:
Content-Type: application/json
Accept: application/json
Body
{
"invitation": {
"file": "Email\nuser_1#gmail.com\nuser_2#gmail.com\nuser_3#gmail.com\nuser_4#gmail.com\n"
}
}
The API response expected for a success call is:
{
"success": true,
"emails": [
"user_1#gmail.com",
"user_2#gmail.com",
"user_3#gmail.com",
"user_4#gmail.com"
]
}
I hope someone can help.
George
If you're not using html form + HTTP POST + encType="multipart/form-data", then you'll need to handle the file upload yourself.
One way to do it: get reference to the input component, listen to changes, when a change happens get the filename from the input reference, read the file, save the data. Here's a component for that:
function FileInput(props) {
const fileInput = useRef(null);
const setRef = ref => {
fileInput.current = ref;
};
async function handleInputChange() {
const { files } = fileInput.current;
props.onChange(files[0]);
}
return (
<input
ref={setRef}
type="file"
placeholder={props.placeholder}
className="join-field-input"
onChange={handleInputChange}
/>
);
}
Use this within the Field component, and the form state will contain the file:
<Field name="invitation[file]" placeholder="Upload csv file">
{({ input, meta, placeholder }) => (
// ...
<FileInput {...input} placeholder={placeholder} />
// ...
)}
</Field>
Also the handleSubmitOnClick gets the whole values object. Your values should look something like this:
values = { invitation: { file: {} } }
So, change the handleSubmitOnClick function to:
const handleSubmitOnClick = values => {
const data = new FormData();
const { file } = values.invitation;
data.append('file', file, file.name);
// ...
}
Here's a codesandbox.

Resources