架构设计思路
- 状态管理:
- 使用React Hook的
useState
来管理局部组件状态,对于应用级别的共享状态,考虑使用useReducer
(结合上下文Context
)或者外部状态管理库如Redux。例如在在线协作绘图工具中,绘图的形状数据、用户当前操作模式等可以用useState
在组件内管理,而整个绘图文档的状态(比如所有用户绘制的图形集合)可通过useReducer
结合Context
来管理。
- Redux适合大型应用,它将状态集中管理,通过action和reducer来更新状态,确保数据一致性。但对于简单应用,
useReducer
和Context
组合通常更轻量。
- API管理:
- 生命周期(旧方式):在
componentDidMount
生命周期方法中进行API的初始请求,例如获取绘图工具的初始配置数据。在componentDidUpdate
中根据组件状态变化决定是否进行后续API请求,比如当用户绘制了一个新图形,需要将新图形数据发送到服务器,此时可在componentDidUpdate
中检查图形数据状态变化并触发API请求。在componentWillUnmount
中取消未完成的API请求,防止内存泄漏,例如使用AbortController
来取消fetch请求。
- Hook机制:使用
useEffect
Hook来替代生命周期方法。useEffect
可在组件挂载和更新时执行副作用操作,包括API请求。通过传递依赖数组,可控制useEffect
的触发时机,例如useEffect(() => { // API请求 }, [dependency])
,只有当dependency
变化时才会重新触发API请求。在useEffect
返回的清理函数中取消未完成的API请求。
- 并发请求处理:
- 使用
Promise.all
来处理多个并发请求。例如在绘图工具中,可能需要同时获取用户配置和绘图模板数据,可将这两个API请求的Promise放入Promise.all
中,当所有请求都成功时,再统一处理数据。
- 若某些请求之间有先后顺序,可使用
async/await
链式调用,确保前一个请求完成后再进行下一个请求。
- 错误处理:
- 对于API请求错误,在
try/catch
块中捕获错误。在生命周期方法中,例如在componentDidMount
的API请求中使用try/catch
,在catch
块中可设置组件的错误状态,从而在UI上显示错误提示。
- 使用Hook时,在
useEffect
的async
函数中同样用try/catch
捕获错误,例如:
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('your - api - url');
const data = await response.json();
// 处理数据
} catch (error) {
setError(error.message);
}
};
fetchData();
}, []);
- 实时更新:
- 利用WebSockets或Server - Sent Events(SSE)来实现实时数据同步。在React组件中,通过
useEffect
在组件挂载时建立WebSocket连接,在useEffect
返回的清理函数中关闭连接。当有新数据通过WebSocket接收时,更新组件状态以触发UI更新。
关键代码示例
- 使用
useState
和useEffect
进行简单API请求:
import React, { useState, useEffect } from'react';
const MyComponent = () => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://example.com/api/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const result = await response.json();
setData(result);
} catch (error) {
setError(error.message);
}
};
fetchData();
}, []);
return (
<div>
{error && <p>{error}</p>}
{data && <pre>{JSON.stringify(data, null, 2)}</pre>}
</div>
);
};
export default MyComponent;
- 使用
Promise.all
处理并发请求:
import React, { useState, useEffect } from'react';
const MyComponent = () => {
const [data1, setData1] = useState(null);
const [data2, setData2] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const [response1, response2] = await Promise.all([
fetch('https://example.com/api/data1'),
fetch('https://example.com/api/data2')
]);
if (!response1.ok ||!response2.ok) {
throw new Error('Network response was not ok');
}
const result1 = await response1.json();
const result2 = await response2.json();
setData1(result1);
setData2(result2);
} catch (error) {
setError(error.message);
}
};
fetchData();
}, []);
return (
<div>
{error && <p>{error}</p>}
{data1 && <pre>{JSON.stringify(data1, null, 2)}</pre>}
{data2 && <pre>{JSON.stringify(data2, null, 2)}</pre>}
</div>
);
};
export default MyComponent;
- 使用
useReducer
和Context
进行状态管理:
import React, { createContext, useReducer } from'react';
// 创建Context
const MyContext = createContext();
// Reducer
const reducer = (state, action) => {
switch (action.type) {
case 'UPDATE_DATA':
return {
...state,
data: action.payload
};
default:
return state;
}
};
const MyProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, { data: null });
return (
<MyContext.Provider value={{ state, dispatch }}>
{children}
</MyContext.Provider>
);
};
export { MyContext, MyProvider };
- 结合WebSockets实现实时更新:
import React, { useState, useEffect } from'react';
const MyComponent = () => {
const [wsData, setWsData] = useState(null);
useEffect(() => {
const socket = new WebSocket('ws://example.com/socket');
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
setWsData(data);
};
return () => {
socket.close();
};
}, []);
return (
<div>
{wsData && <pre>{JSON.stringify(wsData, null, 2)}</pre>}
</div>
);
};
export default MyComponent;