最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to create shared-singleton components across all the platform? - Stack Overflow

programmeradmin4浏览0评论

I'm thinking on creating a React ponent called LoadingMask, where I can show or not (depending on the state) a loading mask from any ponent. 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 ponent 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" ponent, 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 ponents.

Any ideas?

I'm thinking on creating a React ponent called LoadingMask, where I can show or not (depending on the state) a loading mask from any ponent. 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 ponent 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" ponent, 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 ponents.

Any ideas?

Share Improve this question edited Mar 25, 2022 at 19:05 isherwood 61.1k16 gold badges120 silver badges168 bronze badges asked Jun 23, 2017 at 16:42 markaguirmarkaguir 2931 gold badge2 silver badges5 bronze badges 1
  • Why don't you think it's nice to send a callback event handler to show/hide the mask to all pents? If each ponent has a loading state which requires a LoadingMask, why is adding the LoadingMask to each ponent any tidyer than adding a callback to each ponent? – Andy Vennells Commented Dec 1, 2022 at 20:51
Add a ment  | 

2 Answers 2

Reset to default 3

To share data between ponents, you can :

  • Use a lib like Redux, and keep in shared store your mask loader status
  • Use the React context api from your root ponent, 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 ...'
    };
  }
  
  ponentDidMount() {
    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 ...'
    };
  }
  
  ponentDidMount() {
    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./prop-types/prop-types.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.6.1/react-dom.min.js"></script>

<div id="app"></app>

I found this library use-between to be simple, powerful and useful. It removes plexity of redux for sharing data between within functional ponents.

import React, { useState, useCallback } from 'react';
import { useBetween } from 'use-between';

Context/Session.ts

  export const useShareableState = () => {
      const [count, setCount] = useState(0);
      const inc = useCallback(() => setCount(c => c + 1), []);
      const dec = useCallback(() => setCount(c => c - 1), []);
      return {
        count,
        inc,
        dec
      };
    };

App.tsx

import { useBetween } from 'use-between';
import { useShareableState } from './src/Context/Session'
const useSharedCounter = () => useBetween(useShareableState);

const Count = () => {
  const { count } = useSharedCounter();
  return <p>{count}</p>;
};

const Buttons = () => {
  const { inc, dec } = useSharedCounter();
  return (
    <>
      <button onClick={inc}>+</button>
      <button onClick={dec}>-</button>
    </>
  );
};

const App = () => (
  <>
    <Count />
    <Buttons />
    <Count />
    <Buttons />
  </>
);

export default App;
发布评论

评论列表(0)

  1. 暂无评论