I have a indeterminate linear css loading indicator like the ones in material design. Every time I fetch data from a Redux's reducer, I show this indicator. The problem is that while the indicator shows up, it is not being animated. It looks like the whole pages freezes up until the reducer is populated with the data.
Let's suppose I have my loading indicator visible and animated at all times. As soon as I fetch/request data into a reducer, the loading indicator stops animating.
What do you think is causing this? Is it fixable or Do I need to implement a gif indicator and not a css one?
EDIT 1
This is the my Loader component:
import React, { Component, PropTypes } from 'react';
import radium from 'radium';
// indeterminate Linear (type: indeterminateLinear)
const indeterminateLinearLong = radium.keyframes({
'0%': {
left: '-35%',
right: '100%'
},
'60%': {
left: '100%',
right: '-90%'
},
'100%': {
left: '100%',
right: '-90%'
}
});
const indeterminateLinearShort = radium.keyframes({
'0%': {
left: '-200%',
right: '100%'
},
'60%': {
left: '107%',
right: '-8%'
},
'100%': {
left: '107%',
right: '-8%'
}
});
const indeterminateLinear = {
base: {
backgroundColor: '#26a69a',
},
progress: {
position: 'relative',
height: '4px',
display: 'block',
width: '100%',
backgroundColor: '#acece6',
// borderRadius: '2px',
backgroundClip: 'padding-box',
// margin: '0.5rem 0 1rem 0',
overflow: 'hidden',
zIndex: '999'
},
before: {
position: 'absolute',
backgroundColor: 'yellow',
top: '0',
left: '0',
bottom: '0',
willChange: 'left, right',
animation: 'indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite',
animationName: indeterminateLinearLong
},
after: {
position: 'absolute',
backgroundColor: 'yellow',
top: '0',
left: '0',
bottom: '0',
willChange: 'left, right',
animation: 'indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite',
animationName: indeterminateLinearShort,
animationDelay: '1.15s'
}
};
// Indeterminate Cirular (type: indeterminateCircular (default))
const indeterminateCircularRotate = radium.keyframes({
'100%': {
transform: 'rotate(360deg)'
},
});
const indeterminateCircularColor = radium.keyframes({
'100%, 0%': {
stroke: 'red'
},
'40%': {
stroke: 'blue'
},
'60%': {
stroke: 'green'
},
'80%, 90%': {
stroke: 'yellow'
}
});
const indeterminateCircularDash = radium.keyframes({
'0%': {
strokeDasharray: '1,200',
strokeDashoffset: '0'
},
'50%': {
strokeDasharray: '89,200',
strokeDashoffset: '-35'
},
'100%': {
strokeDasharray: '89,200',
strokeDashoffset: '-124'
},
});
const indeterminateCircular = {
loader: {
position: 'absolute',
width: '100px',
height: '100px',
left: '50%',
top: '20%'
},
circular: {
animation: 'x 2s linear infinite',
animationName: indeterminateCircularRotate,
height: '24px',
position: 'relative',
width: '24px'
},
path: {
strokeDasharray: '1,200',
strokeDashoffset: '0',
animation: 'dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite',
animationName: indeterminateCircularDash,
strokeLinecap: 'round',
stroke: 'red',
strokeWidth: '2'
}
}
class Loader extends Component {
render() {
const {
type
} = this.props;
let loader = null;
if ( type === 'indeterminateLinear' ) {
loader = (
<div style={ indeterminateLinear.progress }>
<div style={ indeterminateLinear.before }></div>
<div style={ indeterminateLinear.base }></div>
<div style={ indeterminateLinear.after }></div>
</div>
);
} else {
loader = (
<div>
<div style={ indeterminateCircular.loader }>
<svg style={ indeterminateCircular.circular } viewBox="25 25 50 50">
<circle style={
indeterminateCircular.path
} cx="50" cy="50" r="20" fill="none" strokeMiterlimit="10"/>
</svg>
</div>
</div>
);
}
return (
<div>{ loader }</div>
);
}
}
Loader.propTypes = {
type: PropTypes.string,
};
export default radium(Loader);
When I include the Loader component, it works and animates without a problem; however, when I request some data to be fetched, the animation stops. I can also notice that everything else frozes up too until React rerenders and shows the fetched data.
This Loader component is being included in an top level component that is connected to the reducers, when data is being fetched, the component is being shown.
{ this.props.globalState.someReducer.isFetching ?
<Theme render="Loader" type="indeterminateLinear" /> : null
}
EDIT 2
I want to add another use case. This time has nothing to do with redux, so we can remove it from the picture. It has to be with react itself.
I have a page listing some items, approx. 40 items, and I have a button that sorts this list by date.
This is what I have in my render function:
const sortDesc = ( a, b ) => (
transactions[b].updatedAt ||
transactions[b].createdAt) -
(transactions[a].updatedAt ||
transactions[a].createdAt
)
const sortAsc = ( a, b ) => (
transactions[a].updatedAt ||
transactions[a].createdAt) -
(transactions[b].updatedAt ||
transactions[b]. createdAt
)
let sortDate = sortDesc;
if (!this.state.sortDesc) {
sortDate = sortAsc
}
<button onClick={ this.handleSortBy }>sort by date</button>
{
Object.keys(transactions)
.sort(
sortDate
).map(( key, index )=> {
return (
<div key={ index }>
<Payout {...this.props} />
</div>
);
})
}
I have my Loader component inside a parent component. The structure could be something like this:
-- Layout <-- here we have the Loader
---- Transactions <-- here is the sort function
------ Payout <-- child component
Now, everytime I hit the sort button, everything freezes up until the sorting is finished. When I say "everything" it means all components, including parent components (in this case Layout and Loader).
The Loader is built with Radium.
I must be missing something here, I cannot believe all the components will freeze up when a child componen is re-rendering.