Redux 在存储中返回一个空数组 - Reducer 无法正常工作?
Posted
技术标签:
【中文标题】Redux 在存储中返回一个空数组 - Reducer 无法正常工作?【英文标题】:Redux returning an empty arrays in store - Reducer not working correctly? 【发布时间】:2021-06-13 22:42:56 【问题描述】:我最近第一次将 Redux 放入我的应用程序中,并认为它可以正常工作,但它似乎返回了空数组。我检查了我的 Postman 获取帖子,它在后端运行良好。如果数组为空,如下所示,我的商店是否应该返回值?
可能是什么问题?我有一个异步 Thunk 动作创建器和一个我认为可以正常工作的创建切片 Reducer。
如果我的索引 combineReducer 是 createSlice 都显示为白色,这是否意味着它们不能正常工作? auth 和 message 是黄色的,我的登录工作正常,但是我没有为它们使用 createSlice。
更新:我认为这与我的 extraReducers "state: actionpayload.field" 的语法有关。没有错误消息标记,但我不确定它是否在做它应该做的事情。
或者这可能与我的商店有一个 combineReducer 并通过 createSlice 的 reducer 的事实有关吗? (应该是 Redux 工具包的 configureStore)我的身份验证和消息工作正常,但它们不是 Redux。 configureStore 是否同时允许 createSlice 和普通 switch 语句?
index.js
export default combineReducers(
// combine the reducers
user,
fields,
article,
diveLog,
marineList,
diveSchool,
diveSpot,
admin,
auth,
message
);
减速器
const fieldsSlice = createSlice(
name: 'diveLogFields',
initialState:
current: [],
region: [],
diveType: [],
visibility: [],
diveSpot: [],
,
reducers: ,
extraReducers:
// picks up the success action from the thunk
[requireFieldData.fulfilled.type]: (state, action) =>
// set the property based on the field property in the action
(state: action.payload.field); (state: action.payload.items)
)
export default fieldsSlice.reducer;
动作
export const requireFieldData = createAsyncThunk(
'fields/requireData', // action name
// action expects to be called with the name of the field
async (fields) =>
// you need to define a function to fetch the data by field name
const response = await diveLogFields(fields);
const data = response;
// what we return will be the action payload
return
fields,
items: data.data
;
,
// only fetch when needed
condition: (fields, getState) =>
const field = getState();
// check if there is already data by looking at the array length
if ( field[fields].length > 0 )
// return false to cancel execution
return false;
)
更新
当我尝试呈现我的页面时,我仍然收到以下错误消息。我必须进入我的商店并添加 compose Redux 导入。
此消息表明问题出在哪里?
【问题讨论】:
【参考方案1】:我在您的代码中发现了一些小问题,因此,以下是修复和解释:
切片:
const fieldsSlice = createSlice(
name: 'diveLogFields',
initialState:
current: [],
region: [],
diveType: [],
visibility: [],
diveSpot: [],
fields: [], // Add initial fields array (if you want to store it)
items: [], // Add initial items array (if you want to store it)
,
reducers: ,
extraReducers:
[requireFieldData.fulfilled.type]: (state, action) =>
state.fields = action.payload.fields
state.items = action.payload.items
,
,
)
export default fieldsSlice.reducer
在上面的代码中,你可以使用state.fields = ...
和state.items = ...
来设置状态数据。看起来我们正在直接改变状态,但我们 不是 因为 ...
Redux Toolkit 允许我们在 reducer 中编写“变异”逻辑。它实际上并没有改变状态,因为它使用 Immer 库,该库检测到“草稿状态”的更改并根据这些更改生成一个全新的不可变状态
AsyncThunkAction:
// Assumption, fake async call
function diveLogFields(fields)
return new Promise((resolve) =>
setTimeout(() =>
resolve( data: data: [1, 2, 3] , fields )
, 2000)
)
export const requireFieldData = createAsyncThunk(
'diveLogFields/requireFieldData',
async (fields) =>
const response = await diveLogFields(fields)
const data = response
return
fields,
items: data.data,
,
condition: (fields, getState, extra ) =>
const fields: fieldsState = getState() // getState() returns your Redux State
if (fieldsState.fields.length > 0)
return false // cancel the action if fields has some data
,
)
这是一个调度异步操作的示例:
function MyComponent()
const dispatch = useDispatch()
// for example, make async call below hook
useEffect(() =>
dispatch(requireFieldData([4, 5, 6]))
, [dispatch])
return (
<>i am MyComponent</>
)
现在,这是调度操作后状态的样子:
【讨论】:
感谢 Ajeet,所以这与我的 combineReducer 无关,其中包含 createSlice reducer 和 switch 语句的混合?我已经拆分了我的 index.reducers.js 文件,以便我的 auth 和消息减速器位于组合减速器中,并且 configureStore 包含所有 reduxToolkit 减速器。 其实你的问题我并不清楚。但我选择了您的代码并修复了现有问题。 不要将旧的 reducer 样式(使用 switch)与新的样式(使用 Redux Toolkit)混用。旧样式需要编写太多代码。新样式(使用工具包)需要编写更少的代码。但是如果您需要,您可以将旧样式与新样式混合使用。它会起作用的。但我建议采用新风格,检查redux-toolkit.js.org 您当前的代码是否仍有任何问题(按照我在回答中的建议进行更改后)?so this is nothing to do with my combineReducer containing a mix of createSlice reducers and switch statements?
不。它会工作。 (即将旧的 switch 样式与新的 SliceReducer 混合会起作用)。但它可能看起来令人困惑和肮脏。
@Jimbo Redux Toolkit 只是一个轻松创建reducer 和actions 的助手。从createSlice
获得的reducer 是state
和action
的函数,就像任何其他reducer 一样。当它被调用时,它的工作方式与您使用switch
语句创建的reducer 相同。所以把它们结合起来是没有问题的。【参考方案2】:
搞定了。我不得不将我的 store.js 文件更改为以下文件,因为它之前的设置不同。我还使用了我的回复中建议的代码更改。
const store = createStore(
rootReducer,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
【讨论】:
以上是关于Redux 在存储中返回一个空数组 - Reducer 无法正常工作?的主要内容,如果未能解决你的问题,请参考以下文章
react redux Reduc-saga实现 take put takeEvery createSagaMiddleware等