所以我有这个上下文:
import React, { useState, createContext } from 'react';
import { AuthState } from '../types/auth-state.type';
const initialState = {
isAuthenticated: false,
profile: null,
socket: null,
};
export interface IAuthContext {
authState: AuthState;
setAuthState: React.Dispatch<AuthState>;
}
export const AuthContext = createContext<IAuthContext>({
authState: initialState,
setAuthState: () => {},
});
function AuthContextProvider(props: any) {
const [authState, setAuthState] = useState<AuthState>(initialState);
return <AuthContext.Provider value={{ authState, setAuthState }}>{props.children}</AuthContext.Provider>;
}
export default AuthContextProvider;
连同这个组件:
export const SelectedClientWrapper = ({ children }: ISelectedClientWrapper) => {
const { authState, setAuthState } = useContext(AuthContext);
const { clientsState } = useContext(ClientsContext);
const [cachedClientId, setCachedClientId] = useState<string>('');
useMountEffect(() => {
getCachedSelectedClient().then((r) => {
setCachedClientId(r);
});
});
console.log('profile', authState.profile);
if (!authState.profile) {
console.log(2);
const selectedClient = clientsState.clients.find((client) => client.client_id === cachedClientId);
console.log({ selectedClient });
if (selectedClient) {
console.log(3);
setAuthState({ ...authState, profile: selectedClient });
setCachedClientId('');
}
}
return children;
};
这是我的测试:
export const authenticatedInitial = {
authState: {
isAuthenticated: true,
profile: null,
socket: null,
},
setAuthState: () => {},
};
export const clientsMultipleClientsInitial = {
clientsState: {
isFetching: false,
clients: mockClientsProfiles,
profileToGreet: mockClientsProfiles[0],
hasMultipleClients: true,
},
setClientsState: () => {},
};
export const MockAuthContext = ({ initialValue, children }: IMockAuthContext) => {
return <AuthContext.Provider value={initialValue}>{children}</AuthContext.Provider>;
};
const renderComponent = (
{ initialAuthValue = authenticatedInitial, initialClientsValue = clientsMultipleClientsInitial }: IRenderComponent = {
initialAuthValue: authenticatedInitial,
initialClientsValue: clientsMultipleClientsInitial,
}
): RenderResult =>
render(
<MockAuthContext initialValue={initialAuthValue}>
<MockClientsContext initialValue={initialClientsValue}>
<MockRouterWrapper>
<SelectedClientWrapper>
<I18nextWrapper>
<Route path={RoutesEnum.clients}>
<div>clients</div>
</Route>
<Route path={RoutesEnum.stake}>
<div>stake</div>
</Route>
</I18nextWrapper>
</SelectedClientWrapper>
</MockRouterWrapper>
</MockClientsContext>
</MockAuthContext>
);
所以这一切看起来都不错,也很有意义。
组件的逻辑是:
如果 auth.profile 未设置,则查找可能被缓存的客户端。如果他被缓存,请将其设置为配置文件,并清除状态(这可以防止站点卡在一个客户端上,异步等等)。否则就返回孩子。
当我手动测试时它有效。问题是,当我尝试模拟它时,它不会更新上下文,因此它执行所有魔术,找到用户,在最后一个 if 中运行代码,但上下文未更新,因此它重定向到错误的路线。所以在日志中我得到:
console.log
profile null
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:21:11)
console.log
2
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:23:13)
console.log
{ selectedClient: undefined }
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:25:13)
console.log
profile null
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:21:11)
console.log
2
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:23:13)
console.log
{
selectedClient: {
...... values
}
}
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:25:13)
console.log
3
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:27:15)
console.log
profile null
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:21:11)
console.log
2
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:23:13)
console.log
{ selectedClient: undefined }
at SelectedClientWrapper (src/components/SelectedClientWrapper/SelectedClientWrapper.tsx:25:13)
console.log
<body>
<div>
<div>
clients
</div>
</div>
</body>
为什么不更新上下文?我错过了什么?