我正在通过构建远程REST API的前端来学习React。(如果需要,我可以修改远程API。)到目前为止,我在前端有一个这样的函数:
function FooForm() {
const [inputs, setInputs] = useState({});
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs(values => ({...values, [name]: value}))
}
const handleSubmit = (event) => {
event.preventDefault();
// Here is where I'd post to the API
}
return (
<form onSubmit={handleSubmit}>
<label>Foo
<input
type="text"
name="foo"
value={inputs.foo || ""}
onChange={handleChange}
/>
</label>
<br />
<label>Bar
<input
type="text"
name="bar"
value={inputs.bar || ""}
onChange={handleChange}
/>
</label>
<br />
<input type="submit" />
</form>
)
}
它将POST到API端点。但是,我如何操作表单,使文本字段预加载值从数据库,例如像value={inputs.foo || preload.foo}
,等等?
这个海报回答了他自己的问题,选择以某种方式使用useEffect
钩子,但从上下文中不清楚React/fetch如何处理cookie。这是自动发生的吗?有没有更好的办法?
function FooForm() {
const [inputs, setInputs] = useState({});
+ const init = () => {
+ fetch(/* some setting */).then(res=>setInputs(values => ({...res.data})))
+ }
+ useEffect(()=>{
+ init()
+ },[])
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs(values => ({...values, [name]: value}))
}
const handleSubmit = (event) => {
event.preventDefault();
// Here is where I'd post to the API
}
return (
<form onSubmit={handleSubmit}>
<label>Foo
<input
type="text"
name="foo"
value={inputs.foo || ""}
onChange={handleChange}
/>
</label>
<br />
<label>Bar
<input
type="text"
name="bar"
value={inputs.bar || ""}
onChange={handleChange}
/>
</label>
<br />
<input type="submit" />
</form>
)
}
一些事情,最佳实践是为您的input
'svalue
具有状态inputs
的初始值,在您的情况下是具有属性foo
和bar
的对象,而不是使用||
操作符。
然后在你的HTTP请求中包含cookies,这与React无关,而是你用来发出这些HTTP请求的库。
假设你使用Fetch API,他们的方法是包含一个键值为:credentials: 'include'
的可选对象。
不,你实际上不需要useEffect
钩子在这种情况下,因为你只是POST
请求,useEffect
是必需的,只有当你在同一组件中接收数据,我没有看到你在你当前的代码中这样做,但我可以添加一些例子,因为你提到了。
function FooForm() {
const [inputs, setInputs] = useState({
//initial input values
foo: "",
bar: ""
});
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs(values => ({...values, [name]: value}))
}
//Initialize a state for the expected data
const [dataReceived, setDataReceived] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
// Here is where I'd post to the API
// Let's say you are using 'fetch':
fetch('https://myapi.com', {
//optional property to include credentials(cookies, etc.)
method: 'POST',
credentials: 'include'
//...the rest of your code here
}).then(res => res.json()).then(data => {
setDataReceived(data);
})
}
// For useEffect use-case let's say you are expecting to
// receive some data after the component renders
useEffect(() => {
const fetchNewData = () => {
fetch('https://myapi.com', {
method: 'GET',
credentials: 'include'
}).then(res => res.json()).then(data => {
setDataReceived(data);
})
};
fetchNewData();
// Empty dependency array meaning it only runs
// when the component mounts. If you wish
// it to re-run when different state changes
// then add that state in the dependency array
},[])
return (
<div>
<p>My received data: {dataReceived}</p>
<form onSubmit={handleSubmit}>
<label>Foo
<input
type="text"
name="foo"
value={inputs.foo}
onChange={handleChange}
/>
</label>
<br />
<label>Bar
<input
type="text"
name="bar"
value={inputs.bar}
onChange={handleChange}
/>
</label>
<br />
<input type="submit" />
</form>
</div>
)
}
一个额外的提示:如果你要在你的form
中使用button
元素,默认情况下,它有一个type="submit"
,所以你不必显式地编码它,但它仍然是一个最佳实践,包括它。