我想使用 useContext() 和 useReducer(),剥离 redux 以保存另一个包并学习一种新的状态管理方式。我击中了一个拦截器。
在reducer更新payload之后的登录页面。可以在下面的屏幕截图中看到。我可以看到 Context.Provider 和 reducer 值已更新,但如果我要 console.log('context') 我仍然会得到初始值。
我想在组件之间共享更新的有效负载是 localStorage 本地执行此操作的唯一方法吗?还是我在概念上遗漏了一些东西。
提前致谢。
这是我的 App.tsx
import React from 'react'
import { hot } from 'react-hot-loader/root'
import { AuthProvider } from '~context/authContext'
import { ThemeProvider } from 'styled-components'
import { StoreProvider } from 'easy-peasy'
import theme from '~styles/theme'
import { GlobalStyles } from '~styles/index'
import { Routes } from '~root/routes'
import { store } from '~store/index'
const App = () => (
<ThemeProvider theme={theme}>
<StoreProvider store={store}>
<GlobalStyles />
<AuthProvider>
<Routes />
</AuthProvider>
</StoreProvider>
</ThemeProvider>
)
export default hot(App)
这是我的 AuthProvider:-
import React, { FC, createContext, useReducer } from 'react'
import authReducer, { authInitialState } from '~reducers/authReducer'
import { TState, IAuthProvider } from './types'
export const AuthContext = createContext<[TState, React.Dispatch<any>]>(undefined)
export const AuthProvider: FC<IAuthProvider> = props => {
const authData = useReducer(authReducer, authInitialState)
return <AuthContext.Provider value={authData}>{props.children}</AuthContext.Provider>
}
export const AuthConsumer = AuthContext.Consumer
这是我的 authReducer:-
import { IAuthInitialState, IState, IReducerAction } from './types'
import { actions } from './actions'
export const authInitialState: IAuthInitialState = {
accessToken: null,
isAuthed: false,
error: false,
}
const authReducer = (state: IState, action: IReducerAction) => {
switch (action.type) {
case actions.SET_ACCESS_TOKEN:
return {
...state,
...action.payload,
}
case actions.RESET_ACCESS_TOKEN:
return {
...authInitialState,
}
case actions.ERROR:
return {
...authInitialState,
...action.payload,
}
default:
throw new Error('Unexpected action')
}
}
export default authReducer
这是我的登录页面:-
import React, { FC, useEffect, useContext } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { Container, Col } from 'react-bootstrap'
import { useStoreActions, useStoreState } from '~store/hooks'
import { RedirectState } from '~root/routes/privateRoute'
import { StyledRow } from './styles'
import { AuthContext } from '~context/authContext'
import { getAccessToken } from '~utilities/index'
const Login: FC = () => {
const history = useHistory()
const { state } = useLocation<RedirectState>()
const { isAuthenticated } = useStoreState(({ user }) => user)
const [{ setUserModel }, { setSideNavModel }] = useStoreActions(({ user, sideNav }) => [user, sideNav])
const [context, dispatch] = useContext(AuthContext)
useEffect(() => {
setSideNavModel({ title: 'login', activeChild: 'login' })
const token = getAccessToken()
const authData = {
isAuthed: true,
accessToken: token,
time: Date(),
}
if (token) {
dispatch({
type: 'update',
payload: authData,
})
localStorage.setItem('authedData', JSON.stringify(authData))
}
}, [])
return (
<Container id="page-container">
<StyledRow className="justify-content-md-center">
<Col md="auto"></Col>
</StyledRow>
</Container>
)
}
export default Login