【问题标题】:React toolkit redux extraReducers not workingReact 工具包 redux extraReducers 不工作
【发布时间】:2022-12-11 10:53:50
【问题描述】:

当动作结束时,没有调用 extraReducer

我正在尝试获取此 url,它将向我返回一个项目列表,fetchItems 方法由 dispatch 调用,但最后,未调用第 55 行的额外 reducer。也许我不理解 extraReducers 的逻辑,但它的代码是基于 redux-toolkit 文档

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const fetchItens = createAsyncThunk('table/fetchItens/ful', async (payload, thunkAPI) => {
    let returnedData = null;

    if (payload.serie === 0) {
        console.log(payload)
        await fetch('http://localhost:3006/campeonatos/brasileiraoA').then(async function (response) {
            await response.json().then(function (data) {
                if (data.error) {
                    console.log("Ocorreu um erro.")
                } else {
                    returnedData = data.dados
                }
            });
        }).catch(function (err) {
            console.error('Ocorreu um erro.', err);
        });

    }
    if (payload.serie === 1) {
        console.log(payload)
        await fetch('http://localhost:3006/campeonatos/brasileiraoB').then(async function (response) {
            await response.json().then(function (data) {
                if (data.error) {
                    console.log("Ocorreu um erro.")
                } else {
                    returnedData = data.dados
                }
            });
        }).catch(function (err) {
            console.error('Ocorreu um erro.', err);
        });
    }

    return returnedData;
})

export const slice = createSlice({
    name: 'counter',
    initialState: {
        dates: [

        ]
    },
    reducers: {
        setDate: (state, { payload }) => {
            return {
                ...state,
                dates: payload.dates
            }
        }
    },
    extraReducers: (builder) => {
        builder.addCase(fetchItens.fulfilled, (state, { payload }) => {
            payload.map((item) => state.dates.push(item))
        })
    }
});

export const { setDate } = slice.actions;

export const getDates = (state) => state.dates

export default slice.reducer;

这是商店设置

import navigationReducer from "./navigationSlice";
const { combineReducers, configureStore, getDefaultMiddleware } = require("@reduxjs/toolkit")

export default configureStore(
    {
        reducer: combineReducers({
            selectedElement: navigationReducer
        }),
        
    }
); 

它的名字叫

const { selectedElement } = useSelector(getSelectedElement)

  useEffect(() => {
    // console.log(selectedElement)
    dispatch(fetchItens({
      serie: selectedElement
    }));
  }, [selectedElement])

【问题讨论】:

  • 你的console.log(payload)被执行了吗?
  • 请出示您的商店设置和调用fetchItens 的代码。
  • @ChetanKondawle 是的。它已被执行
  • @phry 见上,请帮忙
  • @ChetanKondawle tks 翻译更正

标签: reactjs react-redux redux-toolkit redux-thunk


【解决方案1】:

您的 getDates 选择器需要是

export const getDates = (state) => state.selectedElement.dates

让它返回undefined以外的任何东西,假设你像这样使用它

const dates = useSelector(getDates)

那可能是你的问题吗?

【讨论】:

  • 不,这不是问题,当提取时,将调用 extraRecucer 来设置日期的状态,如果我将 console.log() 放在 extraRecer 上,则不会执行
  • 上面那片……是你的navigationSlice吗?因为您只是将那个设置为您所在州的一部分 - state.selectedElement。如果你不把 reducer 添加到你的 store,你可以发送你想要的所有东西,reducer 永远不会执行。
  • 很好的观察我的朋友我忘记了,我会应用更改,这应该解决
【解决方案2】:

首先我也在学习redux,会根据我这几周学习redux的个人经验。

你的额外减速器只有在你的承诺得到履行时才会被调用。您的回复可能正在履行。

您同时使用 async/await 语法和 then 的事实使您的代码不是好的做法,并且可能会导致问题。通过有效地使用 async/await 语法,您的异步 thunk 动作创建者将是:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'

// Thunk creator
// Instead of calling he args payload you can get the "serie" directly and using it when dispatching the acion
export const fetchItens = createAsyncThunk('table/fetchItens/ful', async (serie, thunkAPI) => {

// using async/await 
    if (serie === 0) {
        try {
            const response = await fetch('http://localhost:3006/campeonatos/brasileiraoA')
            const returnedData = await response.json()
            return returnedData.dados
        } catch (error) {
            console.log("Ocorreu um erro.")
        }
    }
    if (serie === 1) {
        try {
            const response = await fetch(
              'http://localhost:3006/campeonatos/brasileiraoB'
            )
            const returnedData = await response.json()
            return returnedData.dados
        } catch (error) {
            console.log('Ocorreu um erro.')
        }
        
    }
    return null
})

// Added cases for pending and rejected
export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
      dates: [],
      status: 'idle',
      errors: []
  },
  reducers: {
    setDate: (state, { payload }) => {
      return {
        ...state,
        dates: payload.dates
      }
    }
  },
  extraReducers: builder => {
    builder.addCase(fetchItens.pending, (state) => {
        state.status = 'loading'
    }).addCase(fetchItens.rejected, (state, { payload }) => {
        state.status = 'failed'
        state.errors.push(payload)
    }).addCase(fetchItens.fulfilled, (state, { payload }) => {
        state.status = 'succeded'
      payload.map(item => state.dates.push(item))
    })
  }
})

export const { setDate } = counterSlice.actions

export const getDates = (state) => state.dates

export default counterSlice.reducer

这个文件的名称是什么?这是在 navigationReducer.js 里面吗?由于切片的名称是 counter,我们假设它称为 counterReducer.js。

如果它位于与 navigationReducer.js 不同的文件中,您还需要在定义商店时添加它。我还删除了 getDefaultMiddleware,因为您似乎没有使用它。

import navigationReducer from "./navigationSlice";
import counterReducer from "./counterSlice"; 
import { combineReducers } from 'redux'
import { configureStore } from '@reduxjs/toolkit'


const reducer = combineReducers({
  selectedElement: navigationReducer,
  counter: counterReducer,
  notification: notificationReducer
})

const store = configureStore({
  reducer
})

export default store

由于我不知道您的文件夹结构,因此我还假设您的组件与您的减速器位于同一文件夹中

你的组件.js

import { useEffect } from "react"
import { useSelector, useDispatch } from "react-redux"
import { fetchItens } from "./counterSlice"

const YourComponent = () => {
  const { selectedElement } = useSelector(getSelectedElement)
  const dispatch = useDispatch()

  useEffect(() => {
    console.log(selectedElement)
    // sending selectedElement directly as you are already getting it as args in your thunk creator
    dispatch(fetchItens(selectedElement))
  }, [selectedElement])

  // render something
}

export default YourComponent

}

希望这对您有所帮助。如果您需要,我也许可以尝试通过 dms 用葡萄牙语澄清一些事情。

参考资料:https://redux-toolkit.js.org/api/createAsyncThunk

这是我在 Stack Overflow 中的第一个贡献,我也希望得到一些反馈!

【讨论】:

    猜你喜欢
    • 2021-03-14
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 2021-09-03
    • 2018-10-16
    • 2021-12-10
    相关资源
    最近更新 更多