React Native面试题——Redux之实战项目(3)

一 概述

  1. 如果你负责的 React Native 项目中 Redux 状态过于臃肿,如何重构?
  2. React Native 中 Redux 如何配合分页加载列表?
  3. 如何设计 Redux 状态结构,使其更可维护和可扩展?
  4. 你如何在 Redux 中处理 WebSocket、推送或长连接的消息更新?
  5. 一个 Redux 异步请求失败后如何自动重试?
  6. 如何在 Redux 中实现权限控制?比如用户角色不同,看不同内容

二 面试题解答(仅供参考)

2.1 如果你负责的 React Native 项目中 Redux 状态过于臃肿,如何重构?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
重构思路如下:

一、问题识别:
-Store 状态耦合严重,模块之间相互引用;
-Reducer 太大、逻辑混乱;
-多个组件使用同一个全局字段,难以追踪变动来源。

二、重构方案:
1.模块化拆分:按功能或页面划分 slice(推荐使用 Redux Toolkit);
-比如将 authSlice、userSlice、cartSlice 分开处理;

2.使用 createSlice 替代传统 reducer;
3.统一异步逻辑管理:使用 createAsyncThunk 管理异步;
4.引入 reselect 和 immer 优化性能和可读性;
5.为每个模块添加单元测试,提高稳定性;
6.调整组件的依赖:避免组件依赖整个 store,而是精准订阅某个 slice 状态。

2.2 React Native 中 Redux 如何配合分页加载列表?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
实现思路:
1、状态设计(以帖子列表为例):
{
posts: {
list: [],
page: 1,
pageSize: 10,
loading: false,
hasMore: true,
error: null
}
}

2、异步 action(使用 thunk 或 asyncThunk):
export const fetchPosts = createAsyncThunk(
'posts/fetch',
async ({ page }, thunkAPI) => {
const res = await fetch(`https://api.com/posts?page=${page}`);
return await res.json();
}
);

3、Reducer 处理追加列表:
extraReducers: (builder) => {
builder.addCase(fetchPosts.fulfilled, (state, action) => {
state.list = [...state.list, ...action.payload];
state.page += 1;
state.hasMore = action.payload.length > 0;
});
}

4、前端触发加载更多(如 FlatList onEndReached):
onEndReached={() => {
if (hasMore && !loading) {
dispatch(fetchPosts({ page }));
}
}}

2.3 如何设计 Redux 状态结构,使其更可维护和可扩展?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
设计原则:

1、Normalized State(扁平化设计):
-避免嵌套对象,便于更新和查询;
-可参考 Normalizr 工具或手动实现。
{
users: {
byId: { 1: {...}, 2: {...} },
allIds: [1, 2]
},
posts: {
byId: { 101: {...} },
allIds: [101]
}
}

2、状态分片(slice)结构清晰;
3、状态命名统一、语义清晰,如:auth.token、cart.items;
4、将 UI 状态和业务状态分开(如 loading/error 单独管理);
5、持久化策略清晰:哪些状态需要持久化,哪些不需要;
6、引入类型系统(TS)规范结构,防止误用 key。

2.4 你如何在 Redux 中处理 WebSocket、推送或长连接的消息更新?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1、说明
在 Redux 中可以通过中间件(如 saga 或自定义中间件)来监听 Socket 消息,统一处理并 dispatch 到 store。

二、示例方案(以 WebSocket 为例):
1.建立连接中间件:
const socketMiddleware = store => {
let socket;
return next => action => {
if (action.type === 'SOCKET_CONNECT') {
socket = new WebSocket('wss://...');
socket.onmessage = (e) => {
const data = JSON.parse(e.data);
store.dispatch({ type: 'SOCKET_MESSAGE_RECEIVED', payload: data });
};
}
return next(action);
};
};

2.配合 Redux store 使用:
const store = configureStore({
reducer,
middleware: [socketMiddleware, thunk],
});

3.监听并更新状态:
case 'SOCKET_MESSAGE_RECEIVED':
return {
...state,
messages: [...state.messages, action.payload],
};

2.5 一个 Redux 异步请求失败后如何自动重试?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
可以使用 redux-saga 实现自动重试机制,或在 thunk 中封装逻辑。

1、Saga 示例:
import { call, put, retry } from 'redux-saga/effects';

function* fetchDataSaga() {
try {
const data = yield retry(3, 1000, fetchDataFromAPI);
yield put({ type: 'FETCH_SUCCESS', payload: data });
} catch (err) {
yield put({ type: 'FETCH_FAILED', payload: err });
}
}

2、Thunk 简化版示意:
export const fetchData = () => async (dispatch) => {
let attempts = 3;
while (attempts--) {
try {
const res = await fetch('...');
const data = await res.json();
return dispatch({ type: 'FETCH_SUCCESS', payload: data });
} catch (e) {
if (attempts === 0) dispatch({ type: 'FETCH_FAIL', payload: e });
}
}
};

2.6 如何在 Redux 中实现权限控制?比如用户角色不同,看不同内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1、在 auth 模块中维护 userRole(如 admin / editor / viewer):
auth: {
token: '...',
role: 'admin',
user: {...}
}

2、页面组件使用 useSelector 获取角色:
const role = useSelector(state => state.auth.role);

if (role !== 'admin') {
return <Text>无权限</Text>;
}

3、还可以封装一个权限 HOC 组件:
const withRole = (Component, allowedRoles) => {
return (props) => {
const role = useSelector(state => state.auth.role);
return allowedRoles.includes(role) ?
<Component {...props} /> : <NoAccess />;
};
};

三 总结:Redux 项目面试关注点

面试角度 涉及知识
架构设计 状态划分、模块化、扁平化、异步管理、权限设计
实战能力 分页加载、WebSocket、自动重试、持久化
技术选型 thunk vs saga、redux vs context、RTK vs 原生
性能优化 useSelector + memo、reselect、按需 dispatch
项目经验 如何重构、多人协作规范、组件状态 vs 全局状态