Stefan Stefan - 14 days ago 5
React JSX Question

ReactJS show loader on child component update

I have seen a lot loader plugins that work for the Mount life cycle but none for the update part and I wonder how to handle it?

What I tried was following setup for parent:

class App extends React.Component {
constructor() {
super()
this.state = {loader_wrap:false};
this.hideLoader = this.hideLoader.bind(this);
this.showLoader = this.showLoader.bind(this);
}

hideLoader(){
this.setState({loader_wrap: false});
}

showLoader() {
this.setState({loader_wrap: true});
}

render() {
var loaderStyle;
if (this.state.loader_wrap) {
loaderStyle = {display:"block"};
} else {
loaderStyle = {display:"none"};
}

return (
<div>
<div id="content">
{React.cloneElement(content, {
hideLoader: this.hideLoader,
showLoader: this.showLoader
})}
</div>
<div id="loader-wrap" style={loaderStyle}>
<img className="loader hidden-sm hidden-xs" src='source/file/'>
</div>
</div>
)
}
}


And this is the child calling the methods:

class Childextends React.Component {

constructor() {
super();
this.state = {results:[]};
this.calculate = this.calculate.bind(this);
}

calculate(dict) {
this.props.showLoader();

Actions.action(dict)
.then(results => {
this.setState({results: results});
})
.catch((err) => {
var errResp = JSON.parse(err.response);
console.log(errResp);
this.setState({responseErrors: errResp});
});
}
componentDidMount() {
this.props.hideLoader();
}
componentDidUpdate() {
this.props.hideLoader();
}

componentWillReceiveProps(values){
this.setState({results:values.results});
}

render() {
return (
/*stuff to be returned*/
)
}
}


I also tried to use the Will methods .. which worked even worser :D
Any ideas how to implement this? I use react with flux but don't now how to use it in this case ..

Answer

Why not just call hideLoader() in the callback of the action's promise?

class Childextends React.Component {

    constructor() {
    super();
    this.state = {results:[]};
    this.calculate = this.calculate.bind(this);
}

calculate(dict) {
    this.props.showLoader();

    Actions.action(dict)
      .then(results => {
         this.setState({results: results});
      })
      .catch((err) => {
          var errResp = JSON.parse(err.response);
          console.log(errResp);
          this.setState({responseErrors: errResp});
      })
      .then(() => {            
         this.props.hideLoader();
      });

}

render() {
    return (
       /*stuff to be returned*/
    )
  }
}

Edit: A different approach to the parent component as well - rather than hiding the element with a style, just don't render it if it isn't required.

render() {
  return (
    <div>
     <div id="content">
         {React.cloneElement(content, {
             hideLoader: this.hideLoader,
             showLoader: this.showLoader
          })}
     </div>

     {this.state.loader_wrap &&
        <div id="loader-wrap" style={loaderStyle}>
            <img className="loader hidden-sm hidden-xs" src='source/file/'>
        </div>
     }
    </div>
  )
}
Comments