mobx-persist
mobx-persist copied to clipboard
Hydration didn't complete before componentDidMount
I've got an empty store on componentDidMount so I can't render data on component loading. As I can see via logs store hydrated just after the component was mounted.
I've tried to implement solution from https://github.com/pinqy520/mobx-persist/issues/38 on my root component (App.js) but if user not on index page then componentDidMount with hydration didn't trigger.
import {store} from '../../state';
import Header from '../header';
import Footer from '../footer';
import ErrorBoundry from '../error-boundry';
import './app.css';
import MainPage from '../main-page';
import LoginPage from '../login-page';
import AccountPage from '../account-page';
import {create} from 'mobx-persist';
const hydrate = create({
storage: localStorage,
jsonify: true,
});
@observer
class App extends Component {
async componentDidMount() {
await hydrate('store', store);
console.log('Mounted index page');
}
SearchPage = () => <h2>Search Page</h2>;
AddListingPage = () => <h2>Add Listing Page</h2>;
render() {
return (
<Provider store={store}>
<ErrorBoundry>
<Router>
<div className="app-container">
<Header />
<div className="content-wrapper">
<Route path="/" exact component={MainPage}/>
<Route path="/search" component={this.SearchPage}/>
<Route path="/account" component={AccountPage}/>
<Route path="/login" component={LoginPage}/>
<Route path="/add-listing" component={this.AddListingPage}/>
</div>
<Footer />
</div>
</Router>
</ErrorBoundry>
</Provider>
);
}
}
For example, in AccountPage
store is empty on componentDidMount
. Only way I can check if user logged-in is adding check to componentDidUpdate
.
...
@inject('store')
@withRouter
@observer
class AccountPage extends Component {
state = {
user: Object.assign({}, this.props.store.user.user),
};
componentDidMount() {
console.log('Account', this.props.store.user);
}
componentDidUpdate() {
const {store, history} = this.props;
if(!store.auth.isLogged) {
history.push('/login');
}
}
...
render() {
<div>
{this.props.store.user.user.firstName}
{this.props.store.auth.isLogged}
</div>
}
}
Any suggestions on how to get a hydrated store before component will be mounted on any page? I'm using react-router
Hey, I had a similar issue, where my APIs were getting called from cDM while the hydration was not complete. hence some empty headers and params were being passed. So what I did was, I created a component called PersistStore
that had the responsibility of hydrating all my stores and after all of them were hydrated only then I would render my main app. Here is the code.
const rootStore = new RootStore();
constructor(props: Props) {
super(props);
const p1 = create()('albumsModel', rootStore.albumsModel);
const p2 = create()('userModel', rootStore.userModel);
const p3 = create()('imagesModel', rootStore.imagesModel);
const p4 = create()('contextStore', rootStore.context);
Promise.all([p1, p2, p3, p4])
.then(() => {
this.setHydration(true);
})
.catch(err => {
this.setHydration(true);
throw err;
});
}
@action('Set Hydration flag')
setHydration(x: boolean) {
this.isHydrationComplete = x;
}
render() {
if (!this.isHydrationComplete) return null;
return this.props.render(rootStore.getStores());
}
And this would be a wrapper for your main app. I am using render props pattern but you could easily use hooks.