【发布时间】:2021-07-21 20:37:20
【问题描述】:
我一直在谷歌、官方文档、堆栈溢出中搜索从 React 功能组件(Typescript)访问我的 Redux 存储的方法。从理论上讲,使用各种指南应该很容易做到这一点,但无论我做什么,我都会不断收到未定义的错误。我可以使用自定义类型的选择器钩子和 console.log 获取 store 对象并按预期查看属性,但是在访问它们时,我仍然被拒绝访问。奇怪的是,我能够让它工作的唯一方法是字符串化,然后将存储对象解析为 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/hooks/useTypedSelector.ts
import { useSelector, TypedUseSelectorHook } from 'react-redux'
import { RootState } from '../state'
export const useTypedSelector: TypedUseSelectorHook<RootState> = useSelector
示例
好的,这就是乐趣的开始。
如果我这样做:
const stateA = useTypedSelector((state) => state)
我在 console.log 中得到了整个 store 对象:
{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; }>'
我仍然在 store 对象上记录输出,我有一个想法来字符串化和解析该状态对象,然后我能够访问属性:
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;
}
不确定空对象是关于和/或它是否阻止我访问属性。请帮忙。
【问题讨论】:
标签: javascript reactjs typescript redux