Reputation: 1168
I have a LoadingProvider
where I set the state of my Loading
component to false and when needed to true. I want to show my Loading
component only when the state of loading equals to true.
All my providers
, router
and app
components
are loaded in my root.js
:
import React, { Component } from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { MuiPickersUtilsProvider } from "material-ui-pickers";
import MomentUtils from "@date-io/moment";
import App from "./App";
import { DeleteDialogProvider } from "/hocs/withDeleteDialog";
import { WarningDialogProvider } from "/hocs/withWarningDialog";
import { LoadingProvider } from "/hocs/withLoading";
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import { StateProvider } from "/hocs/withState";
import { I18nProvider } from "/hocs/withI18n";
const theme = createMuiTheme({});
class Root extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>
<MuiPickersUtilsProvider utils={MomentUtils}>
<I18nProvider>
<DeleteDialogProvider>
<WarningDialogProvider>
<StateProvider>
<Router>
<LoadingProvider>
<App />
</LoadingProvider>
</Router>
</StateProvider>
</WarningDialogProvider>
</DeleteDialogProvider>
</I18nProvider>
</MuiPickersUtilsProvider>
</MuiThemeProvider>
);
}
}
export default Root;
My other providers don't block any other components from rendering. But when I add the LoadingProvider
in root.js
and check the console with the React Developer Tools
I see it doesn't load/render the components that comes after my LoadingProvider
component. The problem is that I don't know why it doesn't render any other components.
This is my withLoading
file where I define the LoadingProvider
:
import React, { Component } from "react";
import Loading from "/components/Loading";
const LoadingContext = React.createContext();
export class LoadingProvider extends Component {
constructor(props) {
super(props);
this.state = {
loading: false
};
}
setLoadingContext = e => {
this.setState({
loading: true
});
};
render() {
return (
<LoadingContext.Provider value={this.setLoadingContext}>
<Loading
loading={this.state.loading}
/>
</LoadingContext.Provider>
);
}
}
export const withLoading = Component => props => (
<LoadingContext.Consumer>
{setLoadingContext => (
<Component {...props} setLoadingContext={setLoadingContext} />
)}
</LoadingContext.Consumer>
)
And this is my Loading.js
file where I define my Loading
component:
import React, { Component } from 'react';
import CircularProgress from '@material-ui/core/CircularProgress';
class Loading extends Component {
render() {
const loading = this.props;
// TODO: fix weird repetitive loading prop
if (!loading.loading) {
return null;
} else {
return (
<CircularProgress />
);
}
}
}
export default Loading;
I guess it has something to do with returning null when loading is false. But when I comment that rule of code out it says:
Uncaught Invariant Violation: Loading(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Upvotes: 2
Views: 430
Reputation: 12174
This is primarily because in your LoadingProvider
you are not using props.children
.
<LoadingContext.Provider value={this.setLoadingContext}>
<Loading
loading={this.state.loading}
/>
{this.props.children} // add this
</LoadingContext.Provider>
Take note that null
don't render anything.
Upvotes: 1
Reputation: 31260
Your <App/>
is passed to LoadingProvider in its children
property. But LoadingProvider doesn't do anything with its children, so nothing happens.
So return this.props.children
when you want them to render.
Upvotes: 1