给定的 reduxer 覆盖了其他 reducer 在 react native 中设置的状态

时间:2021-03-11 21:27:04

标签: javascript reactjs react-native react-redux state

我是对原生(和 redux!)做出反应的新手。我正在创建一个非常简单的移动应用程序,它有一个登录和仪表板屏幕。

但是,我遇到了一个问题,当我调用另一个减速器时,它会覆盖并清除其他减速器之前设置的状态。

为了举例说明问题,这里是应用核心设计/代码。 登录屏幕在 Firebase 中登录用户并向以下减速器发送操作:

const initialState = {
    currentUser: null,
    isLogged: false
}

export const user = (state = initialState, action) => {
    return {
        ...state,
        currentUser: action.currentUser,
        isLogged: action.isLogged
    }
}

到目前为止,一切都很好,现在我使用 App.js 将用户发送到仪表板,使用以下代码段:]

<NavigationContainer>
      {
        isLogged ? (
          <Stack.Navigator initialRouteName="DashboardScreen">
            <Stack.Screen name="DashboardScreen" component={DashboardScreen} options={{ headerShown: false }} />
          </Stack.Navigator>
        ) : (
            <Stack.Navigator initialRouteName="LoginScreen">
              <Stack.Screen name="LoginScreen" component={LoginScreen} options={{ headerShown: false }} />
            </Stack.Navigator>
          )
      }
    </NavigationContainer>

在仪表板屏幕中,我有一个按钮可以触发一个操作,该操作会转到以下减速器:

const initialState = {
    lastUpdate: null,
    isSync: false
}

export const db = (state = initialState, action) => {
    return {
        ...state,
        lastUpdate: action.lastUpdate,
        isSync: action.isSync
    }
}

每当我点击按钮时,应用就会返回主屏幕。 “错误”是现在之前设置的 isLogged 变量不是未定义的,导致应用返回登录状态。

我在 App.js 中使用以下代码创建减速器:

import { combineReducers  } from "redux";
import { user } from "./user";
import { db } from "./db";

const Reducers = combineReducers({
    userState: user,
    dbState: db
})

const store = createStore(rootReducer, applyMiddleware(thunk))

很抱歉把问题弄糊涂了,但 React 似乎有太多的样板文件,我无法用更少的行来举例说明发生了什么。我该如何解决这个问题?

提前致谢

1 个答案:

答案 0 :(得分:3)

我认为您的应用有一些问题。首先,您的商店设置有点偏离。我认为您应该按照以下方式声明您的商店:

const rootReducer = combineReducers({
    userState: user,
    dbState: db
})

const store = createStore(rootReducer, applyMiddleware(thunk))

应该传递给 createStore 的第一个值将是您的 combineReducer。您当前仅命名为 Reducer。作为最佳实践,我保留了您的 rootReducer 参数,并简单地更改了组合减速器的名称。

但这并不是您设置的唯一问题。 技术上 Redux 不会为每个分派的操作调用每个单独的减速器(看看我为什么说技术上 read about how combineReducers works here)。但是,出于所有意图和目的,您的组合减速器确实做到了这一点。因此,您需要做的是设置某种系统,其中您的减速器仅在您希望更新状态时更新状态,而不是每次分派操作时.

为了实现这个目标,你应该为你的动作关联一个类型,它会告诉你的减速器每个动作更新哪个状态片。以您的用户减速器为例。每次分派动作时都会访问此reducer。所以现在,当您单击问题中提到的仪表板按钮时,该操作不仅会发送到您的 db reducer,还会发送到由您的 rootReducer 组合的每个 reducer。因此,您可以将操作重构为如下所示:

export const updateLoggedStatus = (isLogged) => (dispatch) => {
  dispatch({
    type: UPDATE_IS_LOGGED,
    isLogged,
  })
}

在此代码段中,您将使用您的操作声明一个类型,我们现在可以在减速器中检查该类型。这将使您的减速器看起来像这样:

const initialState = {
    currentUser: null,
    isLogged: false
}

export const user = (state = initialState, action) => {

    switch(action.type) {
        case: SET_CURRENT_USER:
            return {
                ...state,
                currentUser: action.currentUser
            }
        case: UPDATE_IS_LOGGED:
            return {
                  ...state,
                  isLogged: action.isLogged
            }
        default:
            return state
    }
}

我在这里省略了一些事情,例如在 consts 文件中声明 consts,并将它们导入到操作和 reducer 中,例如。如果您需要更多详细信息,Redux documentation 可能对您的工作非常有帮助。