在使用持久化Redux存储(在TypeScript中)开发React Native应用程序时,我遇到了以下问题:
我构建了一个查询API的Thunk,该API在fetch中返回一组问题数据。这个fetch可以很好地工作,但是当尝试使用extraReducers
将任何数据保存到Redux Store时,我得到了错误。
我的代码如下所示:
首先,我在我的页面中调用了一个分派:
questionpage.tsx
-stuff-
useEffect(() => {
console.log('dispatching fetch')
dispatch(fetchQuestions())
}, []);
-render stuff-
实际的thunk如下所示,并对我的API进行了一次抓取:
export const fetchQuestions = createAsyncThunk('questions/fetchquestions', async () =>{
let headers = new Headers();
headers.append('Authorization', 'Basic ' + Base64.btoa(email + ":" + password))
const response = await fetch(api + "/api/questions", {
headers: headers,
method: 'GET'
})
const stuff = await response.json();
console.log(stuff)
return stuff;
})
然后:
questionSlice
extraReducers: (builder) => {
builder.addCase(fetchQuestions.pending, (state, action) => {
state.status = 'loading' // < when I comment this the console.log works
console.log('pending')
}),
builder.addCase(fetchQuestions.fulfilled, (state, action) => {
state.status = 'succeeded'
// Add any fetched posts to the array
state.questions = state.questions.concat(action.payload) // < comment this, console.log works
console.log('fulfilled')
})
builder.addCase(fetchQuestions.rejected, (state, action) => {
state.status = 'failed' // < when I comment this the console.log works
state.error = action.error.message // < when I comment this the console.log works
console.log('rejected')
})
}
正如您在上面看到的:在我的reducer中,我使用extraReducers
来捕获这个Thunk可以产生的不同结果。这是有效的,但仅当我不修改状态中的任何内容时才有效。如果我尝试将任何内容保存到状态,则会得到以下错误:
[Unhandled promise rejection: Error: [Immer] Immer only supports setting array indices and the 'length' property]
这个错误总是发生,它发生在我修改state.status
时,它是一个字符串,而不是数组,它也发生在我修改state.error
和state.questions
时,最后一个是数组,但另外两个不是。
我查看了很多其他问题,但在任何地方都找不到这个特定的场景,并且完全不知道如何继续。
更新:我的问题源于Immer
。如果我正确理解了文档,Immer
应该允许我更新处于Redux状态的对象,但我无法让它工作:
export const questionSlice = createSlice({
name: 'question',
initialState,
reducers: {
save: (state, action) => {
state.questions.push(action.payload) < this action works
}
},
extraReducers: (builder) => {
builder.addCase(fetchQuestions.fulfilled, (state, action) => {
state.questions.push(action.payload) < this action errors
})
编辑2:
指向这个方向,并在这里发布我的状态。这个应用程序只有一个当前切片,即之前的QuestionSlice,状态如下:
interface questionState {
questions: object[],
status: 'idle' | 'loading' | 'succeeded' | 'failed',
error: string | undefined
}
const initialState: questionState = {
questions : [],
status: 'idle',
error: undefined
}
这将放入RootReducer
中
const rootReducer = combineReducers({questions: questionReducer})
然后这个RootReducer
被用来构建商店:
const persistConfig = {
key: 'root',
storage: AsyncStorage
}
const persistedReducer = persistReducer(persistConfig, rootReducer);
const mystore = createStore(
persistedReducer,
applyMiddleware(thunk)
);```
The comment Phry made pointed towards my state being an array of itself, but that doesn't seem to be the case to me. There's also no code I can find that modifies the state to be an array. I'll try and see if I can make a basic version of the project later that others could look at, but it might be a lot of work with my level of experience.
发布于 2021-05-06 21:25:00
我的解决方法如下:
即使我得到了一个Immer
错误,并且我应该能够在Reducer中进行状态修改,但如果我正确理解了文档:文档中特定于this的部分,它就不能工作。
我认为是extraReducers
中的某些东西导致了Immer
错误。我通过将代码更改为不可变的更新来使代码正常工作。
builder.addCase(fetchQuestions.fulfilled, (state, action) => {
// Add any fetched posts to the array
console.log('fulfilled')
return state = {
...state,
status: 'succeeded',
questions: action.payload
}
})
发布于 2021-05-06 20:30:16
在reducers中,你必须复制你的状态,因为它是不可变的,你不能仅仅改变它的属性。
https://stackoverflow.com/questions/67418074
复制相似问题