Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
197
rated 0 times [  200] [ 3]  / answers: 1 / hits: 21892  / 7 Years ago, fri, june 23, 2017, 12:00:00

I'm thinking on creating a React component called LoadingMask, where I can show or not (depending on the state) a loading mask from any component. The idea is showing it before an ajax call, and hiding it after I receive the data.



I don't want to display two masks at the same time, so if one component is making a request, and another one creates another request, I want to add 1 to my MaskCounter, and substract one when the Request is finished. If the counter is 0, I need to hide the LoadingMask.



I order to do this, I think I need to create a Singleton component, that I can share through the whole platform, so there's only exist one LoadingMask. I also don't think it's nice to send the events to hide/show the mask to all components.



Any ideas?


More From » ajax

 Answers
11

To share data between components, you can :




  • Use a lib like Redux, and keep in shared store your mask loader status

  • Use the React context api from your root component, and share loader status to all childrens. See an example below :





class Application extends React.Component {
constructor() {
super();

this.state = {
nbTasks: 0
};

this.addTask = this.addTask.bind(this);
this.removeTask = this.removeTask.bind(this);
this.isLoading = this.isLoading.bind(this);
}

addTask() {
this.setState(prevState => ({
nbTasks: prevState.nbTasks + 1
}));
}

removeTask() {
this.setState(prevState => ({
nbTasks: prevState.nbTasks - 1
}));
}

isLoading() {
return this.state.nbTasks > 0;
}

getChildContext() {
return {
addTask: this.addTask,
removeTask: this.removeTask,
isLoading: this.isLoading
};
}

render() {
return (
<div>
<ComponentX />
<ComponentY />
<LoadingMask />
</div>
);
}
}

Application.childContextTypes = {
addTask: PropTypes.func,
removeTask: PropTypes.func,
isLoading: PropTypes.func
};

const LoadingMask = (props, context) => (
context.isLoading()
? <div>LOADING ...</div>
: null
);

LoadingMask.contextTypes = {
isLoading: PropTypes.func
};

class ComponentX extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
message: 'Processing ...'
};
}

componentDidMount() {
this.context.addTask();

setTimeout(() => {
this.setState({
message: 'ComponentX ready !'
});

this.context.removeTask();
}, 3500);
}

render() {
return (
<div>
<button disabled>{this.state.message}</button>
</div>
);
}
}

ComponentX.contextTypes = {
addTask: PropTypes.func,
removeTask: PropTypes.func
};

class ComponentY extends React.Component {
constructor(props, context) {
super(props, context);

this.state = {
message: 'Processing ...'
};
}

componentDidMount() {
this.context.addTask();

setTimeout(() => {
this.setState({
message: 'ComponentY ready !'
});

this.context.removeTask();
}, 6000);
}

render() {
return (
<div>
<button disabled>{this.state.message}</button>
</div>
);
}
}

ComponentY.contextTypes = {
addTask: PropTypes.func,
removeTask: PropTypes.func
};

ReactDOM.render(
<Application />,
document.getElementById('app')
);

<script src=https://unpkg.com/prop-types/prop-types.min.js></script>
<script src=https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js></script>
<script src=https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js></script>

<div id=app></app>




[#57325] Wednesday, June 21, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mitchellg

Total Points: 235
Total Questions: 117
Total Answers: 106

Location: Fiji
Member since Wed, Jul 14, 2021
3 Years ago
mitchellg questions
Sun, Jan 10, 21, 00:00, 3 Years ago
Fri, Aug 21, 20, 00:00, 4 Years ago
Fri, Jul 10, 20, 00:00, 4 Years ago
;