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;