我对Context
有疑问。我有两个上下文,AuthenticationProvider
和VehiclesProvider
。
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>
)
}
}
当我们从应用程序注销时,AuthenticationProvider
将更新其自身的状态并将其重置为初始状态。但是我们还需要通过AuthenticationProvder
中的方法,来重置VehiclesProvider
中的状态。
所以我的问题是:是否可以从父上下文访问/修改子上下文中的状态?
这是AuthenticationProvider
中的方法,应该触发重置子上下文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>
)
}
}
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>
)
}
}
我已经找到了一种方法,可以使用React Context完成我所要求的。这不是推荐的解决方案,因为代码变得非常难看且难以理解。但这有效。我仍然可能会更改为MST / Redux。
对于那些感兴趣的人,这里有一个代码沙箱:嗨! 昨天我问了一个问题,关于是否有可能从父上下文中的方法更新子上下文的状态。我完全理解,现在应该使用React Context。
但是经过很多努力,我找到了一种方法。这是一种骇人听闻的方法,因此可能不建议这样做。如果需要从其他组件更新状态,则应使用Redux或MobxStateTree。
对于那些对如何能够通过partent中的方法更新子上下文感兴趣的人,这里是代码沙箱:https://codesandbox.io/s/kn16859z3
答案 0 :(得分:1)
也许这不是一个“答案”,但将其添加为注释很大。 我和@Treycos呆在一起。 看起来您正在尝试将上下文用于并非旨在用于其目的。
1)上下文是将状态,道具等传递给子组件的一种方式。
示例:媒体播放器和一个按钮。
MediaPlayer是一个根组件,它了解媒体的所有知识,并且可以播放,暂停,下一个播放等。PlayButton呈现按钮并使用上下文访问根组件的播放功能。您不在乎视觉层次结构。 PlayButton只需位于MediaPlayer内部。
<MediaPlayer>
<div>
<div>My Media Player</div>
<PlayButton>
</div>
</MediaPlayer>
2)从您的代码看来,您需要管理诸如全局状态之类的东西。为此,您可以使用redux或类似的东西。