上下文 Api、useReducer 和 Typescript - 组件上无法访问计算值
ContextApi, useReducer, & Typescript - calculated value is not accessible on component
抱歉标题有点含糊,但我很难在这里更精确。
所以我有一个 Context/Reducer 逻辑,我在其中使用一些值初始化上下文。然后,我在自定义提供程序上有一个缩减器逻辑,并使用 useMemo
来计算 values
。当试图在组件上访问其中一个值(不在 state/initialState 中)时,打字稿对我很生气,并告诉我该值在 State 上不存在。补救此警告的最佳方法是什么?
我对 Context/Reducer.
的定义如下
interface State {
displaySidebar: boolean
}
const initialState = {
displaySidebar: false
}
type Action =
| {
type: 'OPEN_SIDEBAR'
}
| {
type: 'CLOSE_SIDEBAR'
}
const UIContext = React.createContext<State>(initialState)
UIContext.displayName = 'UIContext'
const uiReducer = (state: State, action: Action): State => {
switch (action.type) {
case 'OPEN_SIDEBAR': {
return {
...state,
displaySidebar: true,
}
}
case 'CLOSE_SIDEBAR': {
return {
...state,
displaySidebar: false,
}
}
}
}
const UIProvider: FC = (props) => {
const [state, dispatch] = React.useReducer(uiReducer, initialState)
const openSidebar = (): void => dispatch({ type: 'OPEN_SIDEBAR' })
const closeSidebar = (): void => dispatch({ type: 'CLOSE_SIDEBAR' })
const value = useMemo(
() => ({
...state,
openSidebar,
closeSidebar,
}),
[state]
)
return <UIContext.Provider value={value} {...props} />
}
export const useUI = () => {
const context = React.useContext(UIContext)
if (context === undefined) {
throw new Error(`useUI must be used within a UIProvider`)
}
return context
}
export const ManagedUIContext: FC = ({ children }) => (
<UIProvider>
<ThemeProvider>{children}</ThemeProvider>
</UIProvider>
)
现在,当我尝试在组件打字稿中使用 const {closeSidebar} = useUI()
时,我很生气并告诉我 Property 'closeSidebar' does not exist on type 'State'.
我明白了,但我无法弄清楚如何正确添加 closeSidebar
到 React.Context
类型。
当您创建上下文时,您告诉 TS 它的类型将是 State
,因此它不希望那里有任何其他内容。如果你想添加额外的字段,你可以创建一个交集类型,state + methods,或者只是 React.createContext<State & {openSidebar : ()=> void, closeSidebar: ()=> void}>
的命名类型。请注意,由于您的初始状态没有方法,您需要将它们设为可选或提供某种虚拟版本。
抱歉标题有点含糊,但我很难在这里更精确。
所以我有一个 Context/Reducer 逻辑,我在其中使用一些值初始化上下文。然后,我在自定义提供程序上有一个缩减器逻辑,并使用 useMemo
来计算 values
。当试图在组件上访问其中一个值(不在 state/initialState 中)时,打字稿对我很生气,并告诉我该值在 State 上不存在。补救此警告的最佳方法是什么?
我对 Context/Reducer.
的定义如下interface State {
displaySidebar: boolean
}
const initialState = {
displaySidebar: false
}
type Action =
| {
type: 'OPEN_SIDEBAR'
}
| {
type: 'CLOSE_SIDEBAR'
}
const UIContext = React.createContext<State>(initialState)
UIContext.displayName = 'UIContext'
const uiReducer = (state: State, action: Action): State => {
switch (action.type) {
case 'OPEN_SIDEBAR': {
return {
...state,
displaySidebar: true,
}
}
case 'CLOSE_SIDEBAR': {
return {
...state,
displaySidebar: false,
}
}
}
}
const UIProvider: FC = (props) => {
const [state, dispatch] = React.useReducer(uiReducer, initialState)
const openSidebar = (): void => dispatch({ type: 'OPEN_SIDEBAR' })
const closeSidebar = (): void => dispatch({ type: 'CLOSE_SIDEBAR' })
const value = useMemo(
() => ({
...state,
openSidebar,
closeSidebar,
}),
[state]
)
return <UIContext.Provider value={value} {...props} />
}
export const useUI = () => {
const context = React.useContext(UIContext)
if (context === undefined) {
throw new Error(`useUI must be used within a UIProvider`)
}
return context
}
export const ManagedUIContext: FC = ({ children }) => (
<UIProvider>
<ThemeProvider>{children}</ThemeProvider>
</UIProvider>
)
现在,当我尝试在组件打字稿中使用 const {closeSidebar} = useUI()
时,我很生气并告诉我 Property 'closeSidebar' does not exist on type 'State'.
我明白了,但我无法弄清楚如何正确添加 closeSidebar
到 React.Context
类型。
当您创建上下文时,您告诉 TS 它的类型将是 State
,因此它不希望那里有任何其他内容。如果你想添加额外的字段,你可以创建一个交集类型,state + methods,或者只是 React.createContext<State & {openSidebar : ()=> void, closeSidebar: ()=> void}>
的命名类型。请注意,由于您的初始状态没有方法,您需要将它们设为可选或提供某种虚拟版本。