首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Redux Thunk,Modifying state: Unhandled rejection: Error:[ Immer ] Immer仅支持设置数组索引和'length‘属性]

Redux Thunk,Modifying state: Unhandled rejection: Error:[ Immer ] Immer仅支持设置数组索引和'length‘属性]
EN

Stack Overflow用户
提问于 2021-05-06 20:24:43
回答 2查看 277关注 0票数 0

在使用持久化Redux存储(在TypeScript中)开发React Native应用程序时,我遇到了以下问题:

我构建了一个查询API的Thunk,该API在fetch中返回一组问题数据。这个fetch可以很好地工作,但是当尝试使用extraReducers将任何数据保存到Redux Store时,我得到了错误。

我的代码如下所示:

首先,我在我的页面中调用了一个分派:

代码语言:javascript
运行
复制
questionpage.tsx

-stuff-

    useEffect(() => {
        console.log('dispatching fetch')
        dispatch(fetchQuestions())

    }, []);

-render stuff-

实际的thunk如下所示,并对我的API进行了一次抓取:

代码语言:javascript
运行
复制
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;

})

然后:

代码语言:javascript
运行
复制
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可以产生的不同结果。这是有效的,但仅当我不修改状态中的任何内容时才有效。如果我尝试将任何内容保存到状态,则会得到以下错误:

代码语言:javascript
运行
复制
[Unhandled promise rejection: Error: [Immer] Immer only supports setting array indices and the 'length' property]

这个错误总是发生,它发生在我修改state.status时,它是一个字符串,而不是数组,它也发生在我修改state.errorstate.questions时,最后一个是数组,但另外两个不是。

我查看了很多其他问题,但在任何地方都找不到这个特定的场景,并且完全不知道如何继续。

更新:我的问题源于Immer。如果我正确理解了文档,Immer应该允许我更新处于Redux状态的对象,但我无法让它工作:

代码语言:javascript
运行
复制
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,状态如下:

代码语言:javascript
运行
复制
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被用来构建商店:

代码语言:javascript
运行
复制
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.
EN

回答 2

Stack Overflow用户

发布于 2021-05-06 21:25:00

我的解决方法如下:

即使我得到了一个Immer错误,并且我应该能够在Reducer中进行状态修改,但如果我正确理解了文档:文档中特定于this的部分,它就不能工作。

我认为是extraReducers中的某些东西导致了Immer错误。我通过将代码更改为不可变的更新来使代码正常工作。

代码语言:javascript
运行
复制
builder.addCase(fetchQuestions.fulfilled, (state, action) => {
            // Add any fetched posts to the array
            console.log('fulfilled')
            
            return state = {
                ...state,
                status: 'succeeded',
                questions: action.payload
            }
        })
票数 1
EN

Stack Overflow用户

发布于 2021-05-06 20:30:16

在reducers中,你必须复制你的状态,因为它是不可变的,你不能仅仅改变它的属性。

read more here

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67418074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档