reactjs - 如何使用 React Redux Hooks 加载 Spinner

标签 reactjs redux react-redux react-hooks

我正在尝试使用react-redux钩子(Hook)(useSelector和useDispatch)加载微调器。我能够获取数据,但不能获取加载程序(在我的例子中为 showLoader 和 hideLoader)

期望:当我单击刷新按钮时,我想加载微调器(在后台它将刷新数据)。在单击按钮之前,我可以使用 useEffect Hook 获取数据。

//ActionCreators.js
export const EVENT_LOG = "EVENT_LOG";
export const EVENT_FAILURE = "EVENT_FAILURE";
export const SHOW_LOADER = "SHOW_LOADER";
export const HIDE_LOADER = "HIDE_LOADER";

//Actions.js

    import {
      EVENT_LOG,
      EVENT_FAILURE,
      SHOW_LOADER,
      HIDE_LOADER,
    } from "./actionCreators";
    import { readList } from "./APIUtilsNew";

    export const readLogs = (path) => {
      return (dispatch) => {
        readList(path)
          .then((data) =>
            dispatch(
              {
                type: EVENT_LOG,
                payload: data,
              },
              console.log("EventLog Actions: ", data)
            )
          )
          .catch((error) => {
            dispatch({
              type: EVENT_FAILURE,
              payload: error,
            });
            throw error;
          });
      };
    };

    export const showLoader = () => (dispatch) => {
      dispatch({
        type: SHOW_LOADER,
      });
    };

    export const hideLoader = () => (dispatch) => {
      dispatch({
        type: HIDE_LOADER,
      });
    };

 //Reducers.js

    import {
      EVENT_LOG,
      EVENT_FAILURE,
      HIDE_LOADER,
      SHOW_LOADER,
    } from "../../actionCreators/index";

    export const initialState = {
      loading: false,
      eventData: [],
      eventError: false,
    };

    const eventReducer = (state = initialState, action) => {
      switch (action.type) {
        case EVENT_LOG:
          return {
            ...state,
            eventData: action.payload,
          };
        case EVENT_FAILURE:
          return {
            ...state,
            eventError: action.payload,
          };
        case HIDE_LOADER:
          return {
            ...state,
            loading: false,
          };
        case SHOW_LOADER:
          return {
            ...state,
            loading: true,
          };

        default:
          return state;
      }
    };

    export default eventReducer;

 //React Component

    import React, { useEffect } from "react";
    import { useSelector, useDispatch } from "react-redux";
    import { readLogs, showLoader, hideLoader } from "./eventActions";
    import { FormattedMessage } from "react-intl";
    import { XGrid } from "@material-ui/x-grid";
    import { CSVLink } from "react-csv";
    import IconBtn from "./IconBtn";
    import MaterialTheme from "./MaterialTheme";
    import { ThemeProvider as MuiThemeProvider } from "@material-ui/core/styles";
    import Refresh from "./Refresh";

    export default function EventsLog() {
      const dispatch = useDispatch();
      const eventLogs = useSelector(
        (state) => state.eventReducer.eventData.data || []
      );
    
      const show = useSelector((state) => state.eventReducer.loading); 
      const hide = useSelector((state) => state.eventReducer.loading);

      useEffect(() => {
        dispatch(readLogs("/events"));
      }, [dispatch]);

      const update = () => {
        dispatch(showLoader());
        dispatch(hideLoader());
      };

      let rows = eventLogs.map((obj, index) => {
        return (rows = {
          id: index + 1,
          Time: obj.time,
          dateTime: obj.dateTime,
          ID: obj.deviceId
        });
      });

      const columns = [
        {
          field: "Time",
          flex: 1,
          type: "dateTime",
          renderHeader: () => <FormattedMessage id={"time"} />
        },
        {
          field: "dateTime",
          flex: 1,
          type: "dateTime",
          renderHeader: () => <FormattedMessage id={"dateTime"} />
        },
        {
          field: "ID",
          flex: 1,
          renderHeader: () => <FormattedMessage id={"id"} />
        }
      ];

      return (
        <div>
          <h1>
            <FormattedMessage id="event.eventLog" />
            <span>
              <IconBtn iconLabel="refresh" />
            </span>
            <CSVLink data={rows} filename={"Log.csv"}>
              <IconBtn iconLabel="cloud_download" onClick={update} />
            </CSVLink>
          </h1>
          <div style={{ height: "90%", width: "100%" }}>
            <MuiThemeProvider theme={MaterialTheme}>
              <Refresh />
              <XGrid
                pageSize={50}
                rowsPerPageOptions={[25, 50, 100]}
                rows={rows}
                columns={columns}
                pagination={true}
                hideFooterSelectedRowCount={true}
              />
            </MuiThemeProvider>
          </div>
        </div>
      );
    }

这是我的微调器所在的组件。我想在加载微调器时获取此组件

//Refresh Component

    import React from "react";

    export default function Refresh() {

    return <div>Spinner....</div>;
    }

我在网上看到了一些例子,我发现一切都在类组件中

 //  component Example

    class FullPageLoader extends Component {
        state = {  }


        render() { 
            const {loading} = this.props;

            if(!loading) return null;

            return ( 
                <div class="loader-container">
                    <div className="loader">
                        <img src={LoaderGif} />
                    </div>
                </div>
             );
        }
    }


    const mapStateToProps = state => ({ loading: state.application.loading })

    export default connect(mapStateToProps)(FullPageLoader);

    // Another Component

     updateProfile = () =>{
        this.props.dispatch( showLoader() )

        Axios.post(`https://jsonplaceholder.typicode.com/users`, { user : { name : 'Test User' } })
          .then(res => {
            console.log( res );

            this.props.dispatch( hideLoader() )
          })
        /* setTimeout(() => {
          this.props.dispatch( hideLoader() )
        }, 2000); */

      }
      
      <Button bsStyle="info" pullRight fill onClick={this.updateProfile} >
                          Update Profile
                        </Button>

有人可以帮助我如何将上述类转换为基于功能的组件,而不是使用 mapStateToProps 来 Hook (或者)请告诉我如何使用 React-Redux Hook 加载微调器。我感谢您的帮助!

最佳答案

更简单的方法是在操作本身中显示和隐藏加载程序。在promise之前,setLoader为true。然后在 then 和 catch 中你可以隐藏加载器。

export const readLogs = (path) => {
      return (dispatch) => {
        showLoader();
        readList(path)
          .then((data) => {
            hideLoader();
            dispatch(
              {
                type: EVENT_LOG,
                payload: data,
              },
              console.log("EventLog Actions: ", data)
            )
          })
          .catch((error) => {
            hideLoader();
            dispatch({
              type: EVENT_FAILURE,
              payload: error,
            });
            throw error;
          });
      };
    };

如果必须在组件本身中完成,您可以添加延迟而不是立即调用它们。这里似乎没有发生任何操作。

const update = () => {
     dispatch(showLoader());
     setTimeout(() => { 
       dispatch(hideLoader());
     }, 1000);
};

关于reactjs - 如何使用 React Redux Hooks 加载 Spinner,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67340959/

相关文章:

reactjs - React-Router的Link-To更新URL但不刷新页面

javascript - 我如何使用 React (JSX) 编写 else if 结构 - 三元表达式不够表达

javascript - React-Redux-Firebase 文档中不寻常的 json 语法。有效吗?

reactjs - 为什么使用react-redux而不仅仅是redux?

javascript - 尝试理解这个 javascript 源代码

javascript - 无法通过 react 导航传递导航 Prop 黑白屏幕

javascript - 如何在 redux 中创建/编辑/删除嵌套结构?

reactjs - 如何在 redux 中将状态值存储为键值对?

javascript - 通过API调用使用react redux进行文件上传

javascript - 数组未定义 - React Redux