I have a form that must serve 2 tasks after submission:
send the form data to the server
redirect to another page
I'm having difficulties making both things happen;
The first one is easily accomplished using <Form action='/blabla'>, but then I get a blank page with the returned information from the server side as text.
The second one is also easily accomplished using <Form onSubmit={handleSubmit}> with the function:
const handleSubmit = (e) => {
e.preventDefault()
fetch('/blabla', {method: 'POST'})
.then(res => res.json())
.then(data => {
history.push('/nextPage')
})
.catch(error => {
alert(error)
})
}
And it works fine, except no data is sent from the form to the server :(
So, can someone explain me please how to get both tasks above done?
Thanks in advance :)
Would be more clear if you can post the as well.
Anyway, only from the snippet I say your fetch doesnot have body field in configuration, like:
fetch('/blabla', {
method: 'POST',
headers: {
'Content-Type': 'application/json' // or 'application/x-www-form-urlencoded'
},
body: JSON.stringify(data), // adjust this according to Content-Type header
})
that might be the reason why there was no data sent to server.
Related
const [data, setData] = useState([]);
const addOne = (newObj) => {
setData((prev) => {
return [newObj, ...prev];
});
};
The above is called and adds a new object to my array when I have finished making calls to my backend.
I get the data from there like so:-
const [posts, refreshPosts, loadingPosts, reachedEnd, resetPosts, addOne] =
usePaginate(
`post/wall/${id}/${toSkip}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
},
setToSkip
);
Then pass the above into the feed component:-
const posts = props.posts.map((item) => {
return <Post data={item} />});
Where I create my post objects from the data, then inside post I create a new post and try to add the returned value to my array through the addOne method that I posted above:-
const handleClick = async () => {
const url = "post";
const options = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
method: "POST",
body: JSON.stringify({ content: value, location: id }),
};
const post = await fetchData(url, options);
reset();
props.addOne(post)};
But it doesn't seem to trigger a re-render. Inside the post component I make calls that depend on the ID of the new object that was added, as an example:-
const [
commentData,
refreshComments,
loadingComments,
reachedEnd,
resetComments,
addOne,
] = usePaginate(
`post/comments/${props.data._id}/${toSkip}`,
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
method: "GET",
},
setToSkip
);
I would expect with a new object, an entirely new post to be created, but it doesn't seem to do that. What seems to happen is that the first element on the page re-renders partially
<div className="postContent">
{profData && props.data.content} </div>
So the text content of the top element on the page changes to reflect the correct text content of the post I'm trying to add, but then if I add a new comment to the new post, then add another post on top of that, only the props.data.content part changes, and the "shell" of the post remains the same (i.e. the entire post doesn't shift down, so the comments remain on the top post of the page, even though they should be on the second post at that point because the top post is now displaying the content from the newest data item).
resetComments();
refreshComments();
refreshLikes();
I can manually fire reach dataloader individually and then everything seems to work as expected, but it feels like I shouldn't have to do it because they should detect that a new item has been added to my array and just create an entirely new post object from it? It doesn't seem to be any issue with my backend because once I refresh the page everything is as should be. I can add any more information required, just didn't want to bloat the post so tried to pick the functions that seemed relevant to the problem, but I know something else could cause a side effect. It has been bugging me for hours.
The git link is here if anyone could have a look a bit more closely: -
https://github.com/Legandjl/odinbook_client
-edit
So far thanks to the comment I have changed return [newObj, ...prev] to return [...prev, newObj] and it seems to work okay when the new post is being rendered last, but then if I try to prepend or unshift the new object, like const newArr = [...prev], newArr.unshift(newObj) I either get a blackscreen or the same issue.
solved with the help of this post:-
problem when adding new item to start of array in react
const posts = props.posts.map((item, i) => {
return <Post key={item._id} data={item} />;
});
posts needed a unique key, tried with index and it didn't work but then used the _id and now all is as expected. Thanks all who tried to help me.
I have 2 questions
I am trying to handle a submission in Formik. I would like to handle the authentication in my backend and then depending on what my backend returns, set an error "Invalid email/password combo" or redirect to a new page (let's say index). Here is the code handling the submission:
handleSubmit(
{email, password}: LoginFormValues,
{props, setSubmitting, setErrors}
){
fetch(backendURL, {
method: "POST",
body: JSON.stringify({username: email, password: password}),
headers: {
'Content-Type': 'application/json'
},
})
.then(response => response.json())
.then(data => {
if(data.token) {
localStorage.setItem("token", data.token)
props.history.push("/")
}else{
//TODO
}
});
}
If the response contains a token then I'll redirect to index however if doesn't then I'd like to display some errors. Is there a way I can do this with Formik or do I need to redirect to the page that contains my form and print an error message there? (If so, how would I do that anyway because I cannot return <Redirect /> (I have to use history.push(...) right?
I am aware that most of the times when you submit a form (and get redirected to a new page), if you try to navigate backwards it'll say something along the lines of "form needs to be resubmitted". However, when I go back in my application it simply renders the form again. Is that something I should be worried about? (What is the motivation in the first place?)
You can handle authentication failure easily with Formik without having to redirect. Following is an example.
handleSubmit(
{email, password}: LoginFormValues,
{props, setSubmitting, setFieldError}
){
fetch(backendURL, {
method: "POST",
body: JSON.stringify({username: email, password: password}),
headers: {
'Content-Type': 'application/json'
},
})
.then(response => response.json())
.then(data => {
if(data.token) {
localStorage.setItem("token", data.token)
props.history.push("/")
}else{
setFieldError("authentication", "Authentication Failed!");
setSubmitting(false);
}
});
}
After this, the error message will be available in errors.authentication. You can replace authentication with whatever name you like because errors is an object. You can now display your error message this way.
{errors.authentication && <div>{errors.authentication}</div>}
You can also use setErrors instead of setFieldError but it will replace the entire error object with a new object.
As for your second question, you do not need to worry about it as long as you ensure no secret or private information is revealed on the form. You can also probably set up a boolean flag in your application to prevent user from seeing the form if the user has logged in by redirecting to a different page, but that is entirely up to you.
Good day!
Im having a weird experience using formik today,
I am currently working on an app that uses formik to handle forms and will do an API request inside the onSubmit() function of formik.
Every thing went well except when i use API request and wait for it's callback.
Somehow the things inside the function of onSubmit will work properly but the API callback value does not return unless i perform a UI Change in the app itself (like pressing random spots on my screen to trigger ui change).
Here is a look of my onSubmit function of formik
onSubmit={values => {
console.log("before")
let response = FunctionWithApiRequest(values);
console.log("after")
response.then((res) => {
console.log(res)
})
}}
and here is my function with api request inside
const FunctionWithApiRequest = (credentials) => {
return fetch(`${AppConfig.HOSTNAME}/v2/auth/signup`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(credentials)
})
.then((response) => response.json())
.then((responseJson) => {
return responseJson
})
.catch((error) => {
console.log(error)
});
}
The return "responseJson" will only appear inside the onsubmit function when i perform a UI Change (like clicking random spots in my react native screen)
i was wondering what is the problem and what cause the bug.
Thank you for your response in advance.
Possibly you can do this in a separate function with await and async.For instance
async handleSubmit(){
let {credentials} = this.state
let data = await this.props.FunctionWithApiRequest(credentials)
this.setState({returnedData: data})
}
And now in your textInput/formik
onSubmit={()=>this.handleSubmit()}
I assume you have made the request api function in actions.file, not in the same file.Am i right?So what i have done is just put await before call.Which means next line will execute only when you have response returned.Comment down if you have any issue.
It was caused by the haul bundler, when you enable dugging mode.
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',
})
})
I need some help regarding the use of Custom Vision. I built an image classifier in order to detect car damages.
So what I am trying to do: when I try to input an image and click the submit button, I want to be able to call the Custom Vision API and get the results in order to be able to analyze them later using ReactJS
I tried using AXIOS and the componentDidMount() method, but I can't seem to get a hold of them.
componentDidMount(){
axios.get('url: "https://southcentralus.api.cognitive.microsoft.com/customvision/v3.0/Prediction/...",
// Request headers {
prediction: ("Prediction-Key","xxx");
content: ("Content-Type","xxx");
},
type: "POST",
// Request body
data: imgContent,
processData: false')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
}
your request type is post and you are using axios.get()
Check your code, // Request headers {
prediction: ("Prediction-Key","xxx");
content: ("Content-Type","xxx");
},
The first bracket seems to be commented out so this may be a potential problem.
You should use async/await with the componentDidMount method.
An example
async componentDidMount() {
const response = await fetch(`https://api.coinmarketcap.com/v1/ticker/?limit=10`);
const json = await response.json();
this.setState({ data: json });
}