无法访问Typed React Redux存储上的属性



我一直在谷歌、官方文档、堆栈溢出中搜索从React功能组件(Typescript(访问我的Redux存储的方法。理论上,使用各种指南应该很容易做到这一点,但无论我做什么,我都会不断出现未定义的错误。我可以使用自定义类型的选择器挂钩和console.log获取存储对象,并按预期查看属性,但在访问它们时,我仍然被拒绝访问。奇怪的是,我能做到这一点的唯一方法是字符串化,然后将存储对象解析为JSON。虽然这确实奏效了,但并不理想,我正在努力找出实现这一目标的正确方法。我相信我已经把它缩小到了一些打字问题上。我还应该注意,我在调度操作以更新存储中的值方面没有问题。我可能没有很好地解释我的场景,所以下面是我的代码和示例来更好地演示:

设置

/src/state/action-types/index.ts:

export enum ActionType {
UPDATE_LOADING_STATUS = 'update_loading_status',
UPDATE_ONLINE_STATUS = 'update_online_status',
UPDATE_APP_LAUNCH_COUNT = 'update_app_launch_count',
}

/src/state/actions/index.ts:

import { ActionType } from '../action-types'
export interface UpdateLoadingStatus {
type: ActionType.UPDATE_LOADING_STATUS
payload: boolean
}
export interface UpdateOnlineStatus {
type: ActionType.UPDATE_ONLINE_STATUS
payload: boolean
}
export interface UpdateAppLaunchCount {
type: ActionType.UPDATE_APP_LAUNCH_COUNT
}
export type Action = UpdateLoadingStatus | UpdateOnlineStatus | UpdateAppLaunchCount

/src/state/reducers/AppStateReducer.ts:

import produce from 'immer'
import { ActionType } from '../action-types'
import { Action } from '../actions'
interface AppState {
isLoading: boolean
isOnline: boolean
isAppVisible: boolean | null
entitlements: string[] | null
persona: string | null
theme: 'light' | 'dark' | 'default'
appLaunchCount: number
}
const initialState: AppState = {
isLoading: true,
isOnline: false,
isAppVisible: null,
entitlements: null,
persona: null,
theme: 'default',
appLaunchCount: 0,
}
export const reducer = produce((state: AppState = initialState, action: Action) => {
switch (action.type) {
case ActionType.UPDATE_LOADING_STATUS:
state.isLoading = action.payload
return state
case ActionType.UPDATE_ONLINE_STATUS:
state.isOnline = action.payload
return state
case ActionType.UPDATE_APP_LAUNCH_COUNT:
state.appLaunchCount = state.appLaunchCount + 1
return state
default:
return state
}
}, initialState)

/src/state/index.ts:

import { combineReducers } from 'redux'
import { reducer as AppStateReducer } from './reducers/AppStateReducer'
export const reducers = combineReducers({
appstate: AppStateReducer,
})
export type RootState = ReturnType<typeof reducers>

/src/state/store.ts:

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { reducer } from './reducers'
import { composeWithDevTools } from 'redux-devtools-extension'
export const store = createStore(
reducer,
{
isLoading: true,
isOnline: false,
isAppVisible: null,
entitlements: null,
persona: null,
theme: 'default',
appLaunchCount: 0,
},
composeWithDevTools(applyMiddleware(thunk))
)

/src/index.tsx:

import * as ReactDom from 'react-dom'
import { Provider } from 'react-redux'
import { store } from './state/store'
import { App } from './components/App'
ReactDom.render(
<Provider store={store}>
<App />
</Provider>,
document.querySelector('#root')
)

/src/components/App.tsx:

import { useEffect } from 'react'
import { useActions } from '../hooks/useActions'
import { useTypedSelector } from '../hooks/useTypedSelector'
import { RootState } from '../state'
export const App: React.FC = () => {
const { updateLoadingStatus, updateOnlineStatus, updateAppLaunchCount } = useActions()
const stateA = useTypedSelector((state) => state)
console.log(state)
return (
...content...
)
}

src/hook/useTypedSelector.ts

import { useSelector, TypedUseSelectorHook } from 'react-redux'
import { RootState } from '../state'
export const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector

示例

好吧,这就是乐趣的开始。

如果我这样做:const stateA = useTypedSelector((state) => state)我在控制台中获得整个存储对象。log:

{isLoading: false, isOnline: true, isAppVisible: null, entitlements: null, persona: null, …}
appLaunchCount: 2
entitlements: null
isAppVisible: null
isLoading: false
isOnline: true
persona: null
theme: "default"
__proto__: Object

但如果我尝试:const stateA = useTypedSelector((state) => state.appLaunchCount)我得到了这个错误,即使输出被正确记录

Property 'appLaunchCount' does not exist on type 'CombinedState<{ appstate: AppState; }>'

我仍然在存储对象上得到一个输出,我有了字符串化和解析该状态对象的想法,然后我就可以访问属性了:const stateB = JSON.parse( useTypedSelector(( state ) => JSON.stringify( state )))

然而,我在网上找到的文件显示,应该可以访问这样的属性:const stateC= useTypedSelector((state) => state.appstate.appLaunchCount),但我得到了这个错误:

Uncaught TypeError: Cannot read property 'appLaunchCount' of undefined

我怀疑这可能是商店的形状或类型的问题,但我不确定我还能尝试什么。最后一条线索是,如果我悬停在RootState对象上,它是这样的:

(alias) type RootState = EmptyObject & {
appstate: AppState;
}

不确定这个空对象是关于和/或它是否阻止我访问属性。请协助。

您的reducer文件和商店设置文件不匹配。

src/state/index.ts:中,您有:

import { combineReducers } from 'redux'
import { reducer as AppStateReducer } from './reducers/AppStateReducer'
export const reducers = combineReducers({
appstate: AppStateReducer,
})
export type RootState = ReturnType<typeof reducers>

src/state/store.ts中,您有:

import { reducer } from './reducers'
import { composeWithDevTools } from 'redux-devtools-extension'
export const store = createStore(
reducer,
// etc
)

如果你仔细观察。。。您已将reducer导入到存储文件中。这就是个人;应用程序状态";切片减少器,而不是您的组合";根减少器";。但是,您导出的TS类型组合根减少器。

因此,您正确地设置了类型,但让运行时行为执行其他操作。

import { reducer }更改为import { reducers },并修复传递给商店的内容以进行匹配,它应该可以正常工作。

附带说明:您应该真正使用我们的官方Redux Toolkit包,并遵循我们TS设置指南的其余部分。这将完全消除所有";动作";文件,reducer中的部分代码,以及存储文件中的其余配置设置。

最新更新