在action之前的传统表单提交方式():
- 用 useState 创建 loading,error,data等状态。 2.给表单的 onSubmit 实践绑定一个函数
- 在函数中用event.perventDefault()阻止浏览器默认行为
- 手动调用 fetch 去请求后端 api
- 在 .then() 和 .catch() 里手动更新 loading,error,data状态。
- 最麻烦的一步 :数据提交成功后,你需要手动重新获取页面上的其他数据来更新 UI(比如列表在新增一个条目后需要刷新)。
javascript
improt React,{ useState,useEffect} from 'react';
// 模拟后端api
const api = {
getTodos:async () =>[{id:1,title:'学习 react'}],
addTodo:async(title) =>({id:Date.now(),title}),
};
function TodesManual(){
//1. 用 useState 创建 loading,error,data 等状态
const [todos,setTodos] = useState([]);
const [isLoading,setRIsLoading] = useState(true);
const [reeor,setError] = useState(null);
const [isSubmitting,setIsSubmitting] = useState(false);
// 表单提交的加载状态
//首次加载数据
const fetchTodos = async() =>{
try{
//接受数据,放入到todos中
const initialTodos = await api.getTodos();
setTodos(initialTodos);
} catch(err){
setError('加载失败');
} finally{
//无论成功失败,数据加载状态结束
setIsLoading(false);
}
};
useEffect(()=>{
fetchTodos();
},[]); //空依赖数组,仅在组件挂载时运行一次
//2. 给表单的 onSubmit 事件绑定一个函数
const handleSubmit = async(event) => {
//3.阻止浏览器默认行为
event.preventDefault();
//提交状态开始
setIsSubmitting(true);
//表单数据更新,标题更新
const formData = new FormData(event.target);
const title = formData.get('title');
//如果标题是空,直接返回
if(!title){
setIsSubmitting(false);
return;
}
try{
//手动调用 fetch去请求后端 api
await api.addTodo(title);
//手动重新获取数据来更新 ui
//每次提交成功后,必须再次调用获取列表的函数
await fetchTodos();
event.target.reset(); //情况输入框
}catch(err){
alert('添加失败!');
}finally{
//手动更新 loading 状态
setIsSubmitting(false);
}
};
if(isLoading) return <p>加载中...</p>
if (error) return <p> {error} <p>
return (
<div>
<h1>待办事项 (手动方式)</h1>
<ul>
{todos.map(todo => <li key={todo.id}>{todo.title}</li>)}
</ul>
<hr />
<form onSubmit={handleSubmit}>
<input type="text" name="title" placeholder="添加新事项..." />
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? '添加中...' : '添加'}
</button>
</form>
</div>
);
}
```
这一串代码的逻辑是,每次打开网页时候,先用 useEffect 调用一次 fetchTodos() 函数,获取api中的数据,并放入Todos 中,在屏幕上打印出来。当表单提交的时候,将数据接受提交到后端,然后再调用 fetchTodos函数,从后端获取数据并打印。