ReactJS:如何在所有平台上创建共享单例组件?

时间:2017-06-23 16:42:24

标签: javascript ajax reactjs

我正在考虑创建一个名为LoadingMask的React组件,我可以在其中显示或不显示(取决于状态)来自任何组件的加载掩码。这个想法是在ajax调用之前显示它,并在我收到数据后隐藏它。

我不想同时显示两个面具,所以如果一个组件正在发出请求,另一个组件创建另一个请求,我想向我的" MaskCounter"添加1。 ,并在请求完成时减去一个。如果计数器为0,我需要隐藏LoadingMask。

我要这样做,我想我需要创建一个" Singleton"我可以通过整个平台共享组件,因此只存在一个LoadingMask。我也不认为发送事件来隐藏/显示所有组件的掩码是很好的。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

要在组件之间共享数据,您可以:

  • 使用像Redux之类的lib,并在共享存储中保留您的掩码加载器状态
  • 使用根组件中的React context api,并将加载器状态共享给所有孩子。请参阅以下示例:



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')
);
&#13;
<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>
&#13;
&#13;
&#13;