【问题标题】:Creating a global spinner by using React and Redux使用 React 和 Redux 创建全局微调器
【发布时间】:2020-07-17 23:58:41
【问题描述】:

我想创建一个可重复使用的微调器,但我不知道实现它的最佳方法是什么。

我尝试了 2 种方法,但需要一些意见,因为我对 React 很陌生。

方法一:

MyComponent.js

const MyComponent = (props) => {
    ...
    return (
        ...
        <Progress showProgress={props.Info.processing} />
        ...
    )
}
const mapStateToProps = (state, ownProps) => {
    return {
        Info: state.Info,
    };
};

export default connect(mapStateToProps)(MyComponent);

Progress.js

const Progress = (props) => {
    ...
    return (
        <Backdrop className={classes.backdrop} open={props.showProgress || false}>
            <CircularProgress color="inherit" />
        </Backdrop>
    );
};
export default React.memo(Progress);

myReducer.js

const initialState = {
    processing: false,
    error: null,
    data: []
    ...
}
const MyReducer = (state = initialState, action) => {
    switch (action.type) {
        case START_PROCESSING: 
            return {...state, processing: true};
        case STOP_PROCESSING: 
            return {...state, processing: false};
    ...         
}

对于这个方法1,它会根据“处理”标志来渲染微调器,但是当我需要微调器时,我需要导入并添加到每个组件中。

方法二

索引.js

import Progress from "common/components/Progress";
ReactDOM.render(
    ...
    <Progress />
    ...,
    document.getElementById("root")
);

layoutReducer.js

const initialState = {
    showProgress: false,
    ...
}
const LayoutReducer = (state = initialState, action) => {
    if (action.type === SHOW_PROGRESS) {
        return {
          ...state,
          showProgress: action.isShow,
        };
    }
    return state;
}
export default LayoutReducer;

Progress.js

import React, { useEffect } from "react";
import { createPortal } from "react-dom";
import { connect } from "react-redux";
...

const progressRoot = document.getElementById("progress-root");
const el = document.createElement("div");

const Progress = (props) => {
  const classes = useStyles();
  useEffect(() => {
    progressRoot.appendChild(el);
  }, []);
  return createPortal(
    <Backdrop className={classes.backdrop} open={props.Layout.showProgress}>
      <CircularProgress color="inherit" />
    </Backdrop>,
    el
  );
};
const mapStateToProps = (state, ownProps) => {
  return { Layout: state.Layout };
};
export default connect(mapStateToProps)(Progress);

对于这个方法 2,我使用 createPortal,并从 layoutReducer 控制微调器。但是对我来说有一个问题,如果我想在获取数据时显示来自其他组件的微调器,我需要使用 dispatch(showProgress(true)) 到 layoutReducer。 但我更喜欢使用每个reducer自己的initialState(处理),例如我的方法1。假设我有createReducer,它应该使用createReduer中的处理标志来控制隐藏/显示微调器,而不是我手动调用调度到布局减速器。

所以我的问题是,如何创建一个全局微调器,它会根据每个组件的“props.processing”标志来隐藏/显示微调器?

更新:我可以通过创建自定义钩子来实现它吗? Hook 是孤立状态,这是否意味着无法共享状态?例如,我只想在需要微调控件的组件上导入并调用 useSpinner()。通过这个钩子,它将根据我的组件道具控制微调器。但是怎么做?如果有人可以提供一些示例代码,将不胜感激。

【问题讨论】:

  • 使用方法 1,因为方法 1 允许您在需要时在任何其他组件中灵活地重用您的组件,在方法 2 的情况下您会丢失

标签: reactjs redux material-ui


【解决方案1】:

您的第二个解决方案在我看来过于复杂。

为了使 Progress 微调器尽可能地可重用,只需让它接受一个布尔属性来判断它是否应该显示,您的第一个解决方案就在正确的轨道上。

试图让一个全局微调器只使用一次,但以某种方式由每个组件触发,很可能不值得付出额外的努力。保持简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2014-10-09
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    相关资源
    最近更新 更多