繁体   English   中英

反应 redux 中的调度类型用法

[英]Dispatch type usage in react redux

在 redux 动作中,当我们想要设置一个值时,我们使用一个类型来调度,如下所示:

dispatch({
    type: SET_LOADER,
    payload: true
})

其中type: SET_LOADER存储在不同的文件中并如下所示导出。

export const SET_LOADER = 'SET_LOADER'

在 reducer 中,我们将这样做:

function initialState() {
    return {
        formErr: {},
        isLoading: false
    }
}

export default function (state = initialState(), action) {
    const { type, payload } = action;
    switch (type) {
        case SET_LOADER:
            return {
                ...state,
                isLoading: payload
            }
        default:
            return state
    }
}

所以在我的应用程序中,我在不同的操作和减速器中使用了这个SET_LOADER类型。 例如,在认证中,在配置文件更新中,当我要加载时,我会使用这种类型。 所以我在各个地方都进口了这种类型。

我不确定是否可以将单一类型用于多用途,因为我现在注意到,当我进行调度时,得到更新的 redux state 不属于目标减速器。 state 更新发生在不同的减速器上。

但它是第一次调度。 下一次更新,它正在更新不正确的 redux state。 在我刷新页面并尝试再次更新后,它就可以工作了。

首先,您需要将减速器分成多个减速器,然后将它们组合在商店中,然后您可能可以通过在多种情况下使用相同的操作来逃脱,但它只是每个减速器的解决方案,这意味着让我们说你有并且 Auth reducer 这个 reducer 将有它的isLoading ,它可能会干扰该 reducer 中的其他操作,例如FetchAllProducts将使用isLoadingFetchByIdProduct正在使用isLoading并且对于将触发加载 state 的其他操作也是如此。

让我们考虑这些使用相同初始 state 的减速器

function initialState() {
    return {
        formErr: {},
        isLoading: false
    }
}

export const authReducer=(state = initialState(), action)=> {
    const { type, payload } = action;
    switch (type) {
        case SET_LOADER:
            return {
                ...state,
                isLoading: payload
            }
        default:
            return state
    }
}
export const productsReducer=(state = initialState(), action)=> {
    const { type, payload } = action;
    switch (type) {
        case SET_LOADER:
            return {
                ...state,
                isLoading: payload
            }
        default:
            return state
    }
}
export const cartReducer =(state = initialState(), action)=> {
    const { type, payload } = action;
    switch (type) {
        case SET_LOADER:
            return {
                ...state,
                isLoading: payload
            }
        default:
            return state
    }
}

//this is the store 
import {createStore,applyMiddleware,compose,combineReducers} from 'redux'
import thunk from 'redux-thunk'
import {productsReducer} from './reducers/ProductReducer'
import {cartReducer} from './reducers/CartReducer'
import {authReducer } from './reducers/AuthReducer'


const initialState={
    products: {
        formErr: {},
        isLoading: false
    },
    cart: {
        formErr: {},
        isLoading: false
    },
    auth: {
        formErr: {},
        isLoading: false
    }
}

const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__  || compose 

const  store = createStore(combineReducers({
        products: productsReducer,
        cart    : cartReducer ,
        auth    : authReducer,
    }),
    initialState,
    composeEnhancer(applyMiddleware(thunk))
)
export default store

即使他们使用相同的初始 state 您,当您将组件连接到 redux 商店时,您可以访问三个不同isLoading

export default connect((state)=>({
    isLoading : state.products.isLoading,
    isLoading2: state.authReducer.isLoading,
    isLoading3: state.cart.isLoading,
}))(Products)

但老实说,我宁愿让我的操作更加明确和具体案例,比如productsFetchIsLoading ,这样可以让你有更多的控制权并防止错误

我现在注意到,当我进行调度时,更新的 redux state 不属于目标减速器。 state 更新发生在不同的减速器上。

每个动作都被分派给每个减速器。 当您调用dispatch({ type: SET_LOADER, payload: true })时,预期的行为是isLoading state 将在每个具有case SET_LOADER的减速器中设置为true

如果您希望加载状态是独立的,那么每个 reducer 都需要一个唯一的string操作类型。


如果您有多个类似的减速器,那么您可以使用工厂 function 来生成类型名称、动作创建函数和减速器案例。 在这里,我们从 Redux Toolkit 扩展createSlice实用程序。

我们传入作为自动生成动作类型前缀的name 、仅此减速器initialState的唯一属性的初始状态以及任何唯一减速器案例。 这将与标准基础 state 合并。

帮手:

const createCustomSlice = ({name, initialState = {}, reducers = {}}) => {
  return createSlice({
    name,
    initialState: {
      formErr: {},
      isLoading: false
      ...initialState,
    },
    reducers: {
      setLoader: (state, action) => {
        state.isLoading = action.payload;
      },
      setFormErr: (state, action) => {
        state.formErr = action.payload;
      }
      ...reducers,
    }
  });
}

用法:

const profileSlice = createCustomSlice({
  name: "profile",
  initialState: {
    username: ""
  },
  reducers: {
    setUsername: (state, action) => {
      state.username = action.payload;
    }
  }
});

// reducer function
const profileReducer = profileSlice.reducer;

// action creator functions
export const { setFormErr, setLoader, setUsername } = profileSlice.actions;

这些动作创建者将创建带有前缀type的动作,例如'profile/setLoader'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM