本篇博客我们将继续完善处理错误,显示加载指示器,实现表单验证,处理跨域请求等。
错误处理:
在前端代码中,我们应当为所有网络请求添加错误处理逻辑。例如,如果后端返回了一个错误码,我们应当在前端捕获到这个错误,并向用户显示一个错误消息。
这里是一个简单的错误处理的例子:
async function handleSubmit(event) {
event.preventDefault();
try {
const response = await axios.post('/api/login', { username, password });
setToken(response.data.token);
} catch (error) {
console.error(error);
if (error.response) {
// 服务器返回了错误响应
alert(`Login failed: ${error.response.data.message}`);
} else {
// 网络请求失败
alert('Login failed: network error');
}
}
}
加载指示器:
如果一个操作需要花费一些时间来完成,例如网络请求,那么我们应该在这个操作进行期间显示一个加载指示器。
下面是如何在请求过程中显示一个加载指示器的例子:
function LoginPage() {
const [loading, setLoading] = useState(false);
// ...
async function handleSubmit(event) {
event.preventDefault();
setLoading(true);
try {
const response = await axios.post('/api/login', { username, password });
setToken(response.data.token);
} catch (error) {
// handle error...
}
setLoading(false);
}
return (
{loading ? Loading...
: null}
{/* other elements... */}
);
}
表单验证:
我们可以使用各种技术和库来实现表单验证,例如HTML5的内置验证功能,或者yup
,joi
等库。
这是一个使用HTML5内置验证功能的例子:
跨域请求:
如果你的前端和后端部署在不同的域名下,你需要配置后端服务器来允许跨域请求。如果你的后端服务器是Express,你可以使用cors
中间件来实现这个功能。
这是配置Express服务器允许所有跨域请求的代码
const cors = require('cors');
app.use(cors());
状态管理库:
如果你的应用的状态变得复杂,你可能需要引入一个状态管理库来帮助你管理状态。Redux和Vuex是两个流行的选择。
在Redux中,你创建一个或多个reducer来处理各种action,然后使用createStore
函数来创建一个store。你可以使用store.dispatch
来发送一个action,然后使用store.getState
来获取当前的状态。你还可以使用react-redux
库来连接你的React组件和Redux store。
在Redux中,创建一个简单的reducer和store的例子如下:
import { createStore } from 'redux';
function reducer(state = { token: null }, action) {
switch (action.type) {
case 'SET_TOKEN':
return { ...state, token: action.payload };
default:
return state;
}
}
const store = createStore(reducer);
然后你可以在你的组件中使用 react-redux
提供的 Provider
和 connect
函数来连接你的 React 组件和 Redux store。
import { Provider } from 'react-redux';
import { connect } from 'react-redux';
function LoginPage({ token, setToken }) {
// ...
}
// 这个函数定义了如何将 Redux store 的状态映射到你的组件的 props
function mapStateToProps(state) {
return { token: state.token };
}
// 这个函数定义了如何将 dispatch 函数映射到你的组件的 props
function mapDispatchToProps(dispatch) {
return {
setToken: token => dispatch({ type: 'SET_TOKEN', payload: token })
};
}
// 使用 connect 函数连接你的组件和 Redux store
const ConnectedLoginPage = connect(mapStateToProps, mapDispatchToProps)(LoginPage);
// 在你的应用中使用 Provider 组件来提供 store
function App() {
return (
);
}
这只是 Redux 的基础使用。在实际的项目中,你可能还需要处理异步 action,组合多个 reducer,以及其他更复杂的用例。你可以查阅 Redux 的文档来了解更多信息。
Context 和 Hooks:
如果你不想使用状态管理库,或者你的项目不大到需要使用状态管理库,那么 Context 和 Hooks 是一个好的选择。在 React 中,你可以使用 Context 来在组件树中传递数据,而不需要通过每一层的 props 来手动传递。而 Hooks 可以让你在函数组件中使用状态和其他 React 特性。
下面是一个使用 Context 和 Hooks 的例子:
import React, { createContext, useState, useContext } from 'react';
const TokenContext = createContext();
function LoginPage() {
const [token, setToken] = useContext(TokenContext);
// ...
}
function App() {
const tokenState = useState(null);
return (
);
}
注意,这只是一种基本的使用方法。在实际的项目中,你可能需要创建多个 context,或者使用更复杂的 hooks,例如 useEffect
,useReducer
,useCallback
,等等。你可以查阅 React 的文档来了解更多信息。