问题
I'm currently experiencing an issue pushing the input field value to state onSubmit.
codesandbox
I'm trying to set an input field value to the state so that I can use that value once the component is updated to redirect the user to another page. I tested the path manually and it works, but since the state is not updating synchronously, the redirect does not work. I can render the input value on the page, but if I try to log it, it long undefined(for the first time) and the previous state on a second submit.
import React, { useRef, useState } from "react";
import { db } from "../firebase";
import { Redirect } from "@reach/router";
function CreateProject(props) {
const [id, setID] = useState(null);
const colorRef = useRef(null);
const projectNameRef = useRef(null);
const handleSubmit = e => {
e.preventDefault();
const project = {
name: projectNameRef.current.value,
colors: [colorRef.current.value],
colorName: colorNameRef.current.value,
createdAt: new Date()
};
setID(projectNameRef.current.value);
db.collection("users")
.doc(`${props.user}`)
.collection("projects")
.doc(`${projectNameRef.current.value}`)
.set({ ...project });
e.target.reset();
};
return id ? (
<Redirect from="/projects/new" to={`projects/:${id}`} noThrow />
) : (
<div>
<div>
<h1>Create new selection</h1>
<form onSubmit={handleSubmit}>
<label>Color</label>
<input ref={colorNameRef} type="text" name="colorName" />
<label>Project Name</label>
<input ref={projectNameRef} type="text" name="projectName" required />
<button type="submit">Submit</button>
</form>
</div>
</div>
);
}
export default CreateProject;
react: 16.8.6
回答1:
That's the way react hooks useState works, to do something after a state change you should perform it inside a useEffect hook, like the following:
useEffect(() => {
if (id) {
console.log(id);
projectNameRef.current.value = ''
}
}, [id])
This effect will run every time the id
value changes (and in the first render) so you could add your logic there and perform your desired actions based on the state change.
回答2:
I think your use of ref
here is inappropriate and may be causing the issue.
I would rewrite your function like this.
function CreateProject() {
const [id, setID] = useState(null);
const [shouldRedirect, setShouldRedirect] = useState(false);
const handleSubmit = e => {
e.preventDefault();
setShouldRedirect(true);
};
const handleChange = (e) => {
setID(e.target.value);
}
return shouldRedirect ? (
<Redirect from="/projects/new" to={`projects/:${id}`} noThrow />
) : (
<div>
<div>
<h1>Create new selection</h1>
<form onSubmit={handleSubmit}>
<label>Project Name</label>
<input onChange={handleChange} type="text" name="projectName" required />
<button type="submit">Submit</button>
</form>
</div>
</div>
);
In this way your state is always being updated and therefore so is your redirect URL. When you submit, you simply tell the component it should now submit with the current ID.
You can see how this works from the React documentation.
You may even be able to replace the conditional render with a functional call to history.push
using withRouter
. See advice on this question.
来源:https://stackoverflow.com/questions/55854831/react-hook-usestate-not-updating-with-onsubmit