Redux 在商店中返回一个空数组 - Reducer 无法正常工作?
Redux returning an empty arrays in store - Reducer not working correctly?
我最近第一次将 Redux 放入我的应用程序中,并认为我可以正常工作,但它似乎返回的是空数组。我检查了我的 Postman get posts,它在后端运行良好。如果像下面这样的数组为空,我的商店是否应该返回值?
可能是什么问题?我有一个异步 Thunk 动作创建器和一个我认为工作正常的创建切片 Reducer。
如果我的索引 combineReducers 和 createSlice 都显示为白色,这是否意味着它们无法正常工作? auth 和 message 是黄色的,我的登录工作正常,但我没有为它们使用 createSlice。
更新: 我认为这与我的 extraReducers“状态:actionpayload.field”的语法有关。没有错误消息标记,但我不确定它是否按预期执行。
或者这可能与我的商店有一个 combineReducer 并通过 createSlice 的减速器这一事实有关吗? (对于 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 导入。
此消息表明问题出在哪里?
我在您的代码中发现了一些小问题,因此,下面是修复和解释:
切片:
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 allows us to write "mutating" logic in reducers. It doesn't actually mutate the state because it uses the Immer library, which detects changes to a "draft state" and produces a brand new immutable state based off those changes
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</>
)
}
现在,这是调度操作后的状态:
成功了。我不得不将我的 store.js 文件更改为以下内容,因为它之前的设置不同。我还使用了回复中建议的代码更改。
const store = createStore(
rootReducer,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
我最近第一次将 Redux 放入我的应用程序中,并认为我可以正常工作,但它似乎返回的是空数组。我检查了我的 Postman get posts,它在后端运行良好。如果像下面这样的数组为空,我的商店是否应该返回值?
可能是什么问题?我有一个异步 Thunk 动作创建器和一个我认为工作正常的创建切片 Reducer。
如果我的索引 combineReducers 和 createSlice 都显示为白色,这是否意味着它们无法正常工作? auth 和 message 是黄色的,我的登录工作正常,但我没有为它们使用 createSlice。
更新: 我认为这与我的 extraReducers“状态:actionpayload.field”的语法有关。没有错误消息标记,但我不确定它是否按预期执行。
或者这可能与我的商店有一个 combineReducer 并通过 createSlice 的减速器这一事实有关吗? (对于 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 导入。
此消息表明问题出在哪里?
我在您的代码中发现了一些小问题,因此,下面是修复和解释:
切片:
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 allows us to write "mutating" logic in reducers. It doesn't actually mutate the state because it uses the Immer library, which detects changes to a "draft state" and produces a brand new immutable state based off those changes
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</>
)
}
现在,这是调度操作后的状态:
成功了。我不得不将我的 store.js 文件更改为以下内容,因为它之前的设置不同。我还使用了回复中建议的代码更改。
const store = createStore(
rootReducer,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;