Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS: How to create shared-singleton components across all the platform?

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?

like image 852
markaguir Avatar asked Jun 23 '17 16:06

markaguir


People also ask

How do you share components between React projects?

Create a folder called lib that stores all the components you want to bring to the other react app. Also define a file called index. js in this folder that exports these components. Create a repo for the components on Github.

How can you embed two or more React components into one?

We can divide the UI of the application into small components and render every component individually on the web page. React allows us to render one component inside another component. It means, we can create the parent-child relationship between the 2 or more components.


1 Answers

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>
like image 158
soywod Avatar answered Sep 28 '22 08:09

soywod