@@ -31,13 +31,18 @@ export default function (mapIonToState) {
3131 // this.props. These are stored differently because anytime the props change, the component has to be
3232 // reconnected to Ion with the new props.
3333 this . activeConnectionIDsWithPropsData = { } ;
34+
35+ this . state = {
36+ loading : true ,
37+ } ;
3438 }
3539
3640 componentDidMount ( ) {
3741 // Subscribe each of the state properties to the proper Ion key
3842 _ . each ( mapIonToState , ( mapping , propertyName ) => {
3943 this . connectMappingToIon ( mapping , propertyName , this . wrappedComponent ) ;
4044 } ) ;
45+ this . checkAndUpdateLoading ( ) ;
4146 }
4247
4348 componentDidUpdate ( prevProps ) {
@@ -53,6 +58,7 @@ export default function (mapIonToState) {
5358 }
5459 }
5560 } ) ;
61+ this . checkAndUpdateLoading ( ) ;
5662 }
5763
5864 componentWillUnmount ( ) {
@@ -61,6 +67,31 @@ export default function (mapIonToState) {
6167 _ . each ( this . activeConnectionIDsWithPropsData , Ion . disconnect ) ;
6268 }
6369
70+ /**
71+ * Makes sure each Ion key we requested has been set to state with a value of some kind.
72+ * We are doing this so that the wrapped component will only render when all the data
73+ * it needs is available to it.
74+ */
75+ checkAndUpdateLoading ( ) {
76+ if ( ! this . state . loading ) {
77+ return ;
78+ }
79+
80+ // Filter all keys by those which we do want to init with stored values
81+ // since keys that are configured to not init with stored values will
82+ // never appear on state when the component mounts - only after they update
83+ // organically.
84+ const requiredKeysForInit = _ . chain ( mapIonToState )
85+ . omit ( config => config . initWithStoredValues === false )
86+ . keys ( )
87+ . value ( ) ;
88+
89+ // All state keys should exist and at least have a value of null
90+ if ( _ . every ( requiredKeysForInit , key => ! _ . isUndefined ( this . state [ key ] ) ) ) {
91+ this . setState ( { loading : false } ) ;
92+ }
93+ }
94+
6495 /**
6596 * Takes a single mapping and binds the state of the component to the store
6697 *
@@ -97,13 +128,21 @@ export default function (mapIonToState) {
97128 }
98129
99130 render ( ) {
131+ if ( this . state . loading ) {
132+ return null ;
133+ }
134+
135+ // Remove any internal state properties used by withIon
136+ // that should not be passed to a wrapped component
137+ const stateToPass = _ . omit ( this . state , 'loading' ) ;
138+
100139 // Spreading props and state is necessary in an HOC where the data cannot be predicted
101140 return (
102141 < WrappedComponent
103142 // eslint-disable-next-line react/jsx-props-no-spreading
104143 { ...this . props }
105144 // eslint-disable-next-line react/jsx-props-no-spreading
106- { ...this . state }
145+ { ...stateToPass }
107146 />
108147 ) ;
109148 }
0 commit comments