Strapi POST API call issue - reactjs

Why Strapi POST Call, always expecting Multi-Part request
I Don't have multi-part data in the particular content Type.
In Strapi CMS Portal, Roles & permission section, I have given access to CREATE
Post Data
Response
import React, { useState } from 'react'
export default () => {
const [description, setDescription] = useState('')
const handleSubmit = async (event) => {
event.preventDefault();
const data = await fetch('http://localhost:1337/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
description
})
})
const response = await data.json();
console.log(response)
}
return (
<div className="Create">
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Description"
value={description}
onChange={(event) => {
setDescription(event.target.value)
}}
/>
<button>Submit</button>
</form>
</div>
)
}

Technology stack which I'm using in this project
Frontend: Reactjs
Backend: Strapi
When I face this issue, I may not be aware of it. What is happening in the backend(Strapi).
Thinks found after I face this issue:
When you create a new collection type in strapi CMS. Strapi will automatically create 4 Folders [config, controllers, models, services], inside the api folder, for customization purposes.
The issue, which I faced is based on the conditions which are added in the controller's folder file (post.js), then I removed that code & tried to hit that POST API call, it's working fine. Without any error.
Helpful Resource, i found in strapi documentaion:
https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#controllers
Strapi Create Customization code file in the controller file.

Related

React Display PDF from authenticated backend

I have a React Frontend and Django Backend. In my frontend I want to include a view for the PDF obtained by the backend. I tried using iframe and object HTML Tags, but they failed due to the missing authentication. My suggested approach would be requesting the PDF with axios.get, since this automatically handles the authentication. However, I could not find out how to handle the obtained PDF in case of temporarily storing and displaying it with react.
Currently my function is able to obtain the PDF and display it in a new window but I want to include it as an element within the current page.
const getPDF = () => {
axios
.get(
`${process.env.REACT_APP_API}/Link/to/the/PDF/`,
{
responseType: "blob",
}
)
.then((r) => {
window.open(URL.createObjectURL(r.data));
});
};
#react-pdf/renderer is used to render pdf from your page/application and is not made to render already made pdfs
You can use react-pdf to do what you want. It works great and lets you style your component the way you want.
In the content of the page I put the following:
<iframe src="" width={600} height={600} />
And I adapted the function to fill the iframe:
const getPDF = () => {
console.log("getPDF");
axios
.get(`${process.env.REACT_APP_API}/Link/to/the/PDF/`, {
responseType: "blob",
})
.then((r) => {
console.log(r.data);
const file = window.URL.createObjectURL(r.data
);
const iframe = document.querySelector("iframe");
if (iframe?.src) iframe.src = file;
})
.catch((err: AxiosError) => {
console.log(err);
});
};
So you have half the work done! in the other half, maybe an option is to look at this component:
#react-pdf/renderer
I used this package without any complaints.
** Sorry for redirecting to the wrong library. I use this instead:
pdf-viewer-reactjs

How to create an approval post in Reactjs?

I need to approve "posts" before going online,
the first question is do I need to code on the backend, or I can do it only in the front-end in order to add the functionality?
so I have some code that creates a post, and I need to send data to the confirmation page before going to the main page.
here is the code for post creation:
const onSubmit = (data) => {
if (data.postText) {
const formData = postToFormData(data, file, createTags);
axios
.post(`/posts`, formData, {
headers: {
"Content-Type": "multipart/form-data",
accessToken: localStorage.getItem("accessToken"),
},
})
.then((res) => {
setTimeout(() => {
history.push("/approving");
}, 2000);
});
setMessage("posct created successfully!");
}
};
so as you see in the code above, we have a post method to post the data, and I need to send the data to the approving page where I need to see all the data and press "approve" or "reject"
i have 3 states in the main page to display the data:
#{value.fullName}
{value.postTitle}
{value.postText}
I would appreciate your help.
I think that you don't need to modify the backend. Only send a PUT request to update the post (if the backend accept this).
Regarding the other question, you don't need to redirect to another url to show new content in react. You can show different content depending in the state.
const Form = ({submitting, handleSubmit, formData, setFormData}) => {
return <form onSubmit={handleSubmit}>
<input
type="text"
required
value={formData.text}
onChange={(e) => setFormData({text: e.target.value})}
/>
<br />
<button type="submit">{submitting ? 'Sending...' : 'Save'}</button>
</form>
}
const Revision = ({formData}) => {
return <div>
<p>Your sucess message...</p>
<p>{formData.text }</p>
<button>Approve</button>
<button>Reject</button>
</div>
}
const App = () => {
const [submitting, setSubmitting] = React.useState(false)
const [submitted, setSubmitted] = React.useState(false)
const [formData, setFormData] = React.useState({text: ''})
const handleSubmit = (e) => {
e.preventDefault()
setSubmitting(true)
// Fake send post data
setTimeout(() => {
setSubmitted(true)
}, 1000)
}
const handleApprove = () => {
// Send PUT request to update your post.
}
const handleReject = () => {
// Send PUT request to update your post.
}
if (submitted) {
return <Revision
formData={formData}
handleApprove={handleApprove}
handleReject={handleReject}
/>
} else {
return <Form
submitting={submitting}
handleSubmit={handleSubmit}
formData={formData}
setFormData={setFormData}
/>
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script crossorigin src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
<div id="container"></div>
I don't quite understand what you means by "approve post before going online". But here the scenarios which I think I understood:-
a) CONFIRMATION FEATURE before submitting new post to backend (basically create a new set of data in the database) javascript
b) APPROVE or REJECT FEATURES after new post successfully submitted & created in the database
For SCENARIO A:-
you may create a component (like a popup or something) that shows user to choose whether they want to Confirm or Cancel creation of new post data.
Confirm - will triggered the onSubmit function and send the data to the backend to create a new post
Cancel - will reset every states to it's default value/state (basically emptying out every input placeholders)
For SCENARIO B:-
you must have some kind of variables in the database that can distinguish which post is approved & which is not. (like status or publish_status - can be set to either Yes or No or 1 or 0)
create a new function to handle just changing/update of status/publish_status var/value in the database of said/selected post. This can be done right after creation of new post (like what you want) or just at anytime you want (basically you have a working UI that handles a list of posts with just the id, title, status/publish_status & action buttons like edit, delete and/or publish, typically we display this in table - so if you hit action button publish, then it will triggered the update/put req to change/update the status/publish_status in the database. Just make sure to change your publish action button text to unpublish if the put req successful)

AWS S3 403 Forbitten error when trying to upload a image with React

I am trying to implement an image upload system on my React app and upload that image to
AWS S. With the code I have when I upload the image I get an error 403 forbidden.
I have tried multiple methods nothing works, I have checked the settings a hundred times still the same error message. Of course when the credentials are not okay I get 400 error bad request. Is this client side problem or server side?
I am also using CORS add-on to bypass, it works with other APIs no problem.
Here is the simple code I am using
import S3FileUpload from 'react-s3';
import React from 'react'
import S3 from 'react-aws-s3'
const FileUpload = () => {
const fileuploader= (e) => {
const config = {
bucketName: process.env.REACT_APP_BUCKET_NAME,
region: process.env.REACT_APP_REGION,
accessKeyId:process.env.REACT_APP_ACCESS_ID,
secretAccessKey:process.env.REACT_APP_ACCESS_KEY
}
const file = e.target.files[0]
console.log(file)
const ReactS3Client = new S3(config)
ReactS3Client.uploadFile(file,config)
.then( data => {console.log(data)})
.catch(err => alert(err))
}
return(
<>
<input
type="file"
onChange={fileuploader}
/>
</>
)
}
export default FileUpload
Thank you for reading my post.

How to handle POST request in reactjs?

I have my ReactJS app running in http://localhost:3000/. I am receiving below form data to my React page as a POST request
<form action="http://localhost:3000/" method="post">
Employee Id: <input type="text" name="eid"><br>
Department Id: <input type="text" name="did"><br>
<input type="submit" value="Submit">
</form>
My react app should be able to handle this POST request and render the UI as below
<h1>{eid}</h1>
<h1>{did}</h1>
I am able to handle GET request using react router but struggling to handle POST request. How can I achieve this?
That is not possible if your React app is static(not server side rendered).
When you send some POST request to your react app, nginx(or other server) will not allow that kind of action(you cannot post to static files)
Even if you bypass that restriction, react script will not have any data from your POST request, because nginx will process your request and return just a html with react script to you
It will not work like php.. you need to have something like backend (node or php to pass the data) or even some site to accept the request..
First, you need maybe some theoretical view:
https://pusher.com/tutorials/consume-restful-api-react
https://www.robinwieruch.de/react-hooks-fetch-data
You should firstly save data
You save them to the state
You display them in the part where it is rendered
To download data from api (GET)- you don't do it directly in form - you only use either ComponentDidMount or UseEffect.
componentDidMount() {
fetch(ApiURL)
.then(res => res.json())
.then(res => this.setState({ planets: res }))
.catch(() => this.setState({ hasErrors: true }));
}
useEffect(async () => {
const result = await axios(
ApiURL,
);
setData(result.data);
});
To send data to api (POST)- It's complicated - you need information about client-server communication
Straight from the React docs:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})

Prevent Redirect on File Upload through form Submittal (React, Express, Multer)

I'm setting up a file uploading functionality for the first time. I have a react front-end and an express server that will store the files. I have it set up so a user can submit the file and it is saved the way I'd like it to be saved on the express server. However, whenever a user submits the form they are redirected from the react frontend (on port 3000) to the POST route on the server (port 3050). I didn't know that this was default behavior for a post request, which I expected would keep the users on the page.
I'd like to avoid this behavior but am unsure of the best way to go about it. I've tried building an action that functions as an AXIOS request, but am having trouble accessing the form data (particularly the file data) in the AXIOS request. My understanding is that there isn't native support for multipart form-data in AXIOS.
Event.preventdefault is the obvious choice, but any implementation of that stops the form submittal from grabbing the appropriate form data and sending it through.
The code for the form is included below (this version is using an on-click event that prevents the event default and dispatches the action - the action fires but as noted doesn't pass any of the relevant information through):
<div className="modal-wrapper">
<h3 className="title__h3">Upload Data</h3>
<p>Drag and drop anywhere or choose a file to upload.</p>
<p>.csv or .xlsx</p>
<form className="upload-form" ref="uploadForm" id="uploadForm" action="http://localhost:3050/upload" method="POST" enctype="multipart/form-data">
<input name="fileName" placeholder="Name the file you're uploading here"/>
<input type="file" name="upl" id="file" className="inputfile" />
<label htmlFor="file" className="btn btn__white-outline btn__full-width">Select a File</label>
<input onClick={this.submitForm} type="submit" value="submit" />
</form>
</div>;
My simple Multer route:
app.post('/upload', upload.single('upl'), function(req,res,next) {
return false
})
My understanding is that there is no native support for sending a multipart-form item through Axios, I'd like to avoid pulling in a FormData module in order to make it work since the form (other than the redirect) works flawlessly. Is there a simple solution here that will prevent the form from trying to load the server-side page while still submitting the form data?
In your submitForm handler, pass a reference to the event and use event.preventDefault().
submitForm(event) {
event.preventDefault();
...other code here...
}
You can also try
<form className="upload-form" ref="uploadForm" id="uploadForm" action="http://localhost:3050/upload" method="POST" enctype="multipart/form-data" onSubmit={ (event) => { event.preventDefault(); } }>
Here is how I handle submitting files with Axios
handleChange = ( event ) => {
const fileReader = new FileReader();
const fileToUpload = event.target.files[0];
fileReader.onload = ( upload ) => {
const allFiles = [ ...this.state.allFiles ].concat( upload.target.result );
this.setState({
allFiles
});
};
fileReader.readAsDataURL(fileToUpload);
};
The handleChange method is tied to the onChange event of the <input type="file" onChange={this.handleChange} />
Then in the form submit handler
handleSubmit = ( event ) => {
event.preventDefault(); //So the page does not refresh
const { allFiles } = this.state;
const Promises = [];
allFiles.forEach( file => {
Promises.push( Axios({
url: "a url goes here",
method: "POST",
data: {
file: file, //This is a data url version of the file
}
}));
});
Axios.all(Promises).then( result => {
alert(result.message); //Display if it uploaded correctly
})
};
create a method in your Component that handles the submit, in the onSubmit attribute of your form call it like: onSubmit="{this.handleSubmit}" and post your data in an async way.

Resources