I have an issue with Context. I have two contexts, AuthenticationProviderand VehiclesProvider.
App.tsx
import { AuthenticationProvider, VehiclesProvider } from '../contexts/
export class App extends React.Component {
public render() {
return (
<ThemeProvider theme={theme}>
<I18nextProvider i18n={i18nConfig}>
<GlobalStyle />
<AuthenticationProvider>
<VehiclesProvider>
<AppRouter />
</VehiclesProvider>
</AuthenticationProvider>
</I18nextProvider>
</ThemeProvider>
)
}
}
When we log out from the app the AuthenticationProvider updates its own state and resets it to initial state. But what we need to do is also, from a method in AuthenticationProvder, is to reset the state in VehiclesProvider.
So my question is: Is it possible from a Parent Context to access/modify state in a Child Context?
AuthenticationProvider.tsx
This is the method in AuthenticationProvider which should trigger a reset of the child context, VehiclesProvider.
export class AuthenticationProvider extends React.Component<
IAuthenticationProviderProps,
IAuthenticationProviderState
> {
public state = {
isAuthenticated: false,
data: undefined,
}
// THIS METHOD MUST TRIGGER `resetFetchedVehicles` in `VehiclesContext`
/**
* **Update context to logged in state**
*
* Save response from API to context. Also let the app know that the user is authenticated.
*
* @memberof AuthenticationProvider
*/
public login = (data: UserClass) => {
const sameUser = this.isSameUser(data.Id)
// If it is not the same user, then reset the VehcilesContext
// if(!sameUser) this.props.resetFetchedVehicles()
if(sameUser) this.METHODINCHILDCONTEXT.resetFetchedVehicles() // THIS IS WHERE THE STATE IN VEHICLESPROVIDER MUST BE MODIFIED
this.setState({
isAuthenticated: true,
data,
})
}
public render() {
return (
<VehiclesConsumer>
{(context) => (
<AuthenticationContext.Provider
value={{
isAuthenticated: this.state.isAuthenticated,
data: this.state.data,
login: this.login,
logout: this.logout,
isSameUser: this.isSameUser
}}
>
{this.props.children}
</AuthenticationContext.Provider>
)}
</VehiclesConsumer>
)
}
}
VehiclesContext.tsx
export class VehiclesProvider extends React.Component<
IVehiclesProviderProps,
IVehiclesProviderState
> {
public state: IVehiclesProviderState = {
loading: false,
fetchedVehicles: [],
totalVehicles: 0,
}
// THIS METHOD MUST BE TRIGGERED FROM `logout` in `AuthenticationContext`
/**
* **Remove all the fecthed vehicles from state**
*
* @memberof VehiclesProvider
*/
resetFetchedVehicles = () => {
this.setState({
fetchedVehicles: []
})
}
public render() {
return (
<VehiclesContext.Provider
value={{
loading: this.state.loading,
fetchedVehicles: this.state.fetchedVehicles,
fetchVehicles: async () => await this.fetchVehicles(),
updateUserVehicleInfo: vehicle => this.updateVehicleInfo(vehicle),
resetFetchedVehicles: () => null
}}
>
{this.props.children}
</VehiclesContext.Provider>
)
}
}
UPDATE
I have found a way to be able to do what I was asking for, with React Context. It is NOT a recommmended solution, since the code gets very ugly and hard to understand. But it works. I will still probably change to MST/Redux.
For those who are intersted, here is a Code Sandbox: Hi! Yesterday I asked a question regarding if it was possible to update a child context's state from a method in a parent context. I totally understand that it is now how React Context is supposed to be used.
But after a lot of struggling I have found a way to do it. It is a hacky way, and it is probably not recommended. If you need to update state from different components you should use Redux or MobxStateTree.
For those who are interested in how to be able to update a child context from a method in the partent, here is a Code Sandbox: https://codesandbox.io/s/kn16859z3