首页 > 解决方案 > 使用 React 和 Redux 创建全局微调器

问题描述

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

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

方法一:

我的组件.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()。通过这个钩子,它将根据我的组件道具控制微调器。但是怎么做?如果有人可以显示一些示例代码,将不胜感激。

标签: reactjsreduxmaterial-ui

解决方案


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

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

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


推荐阅读