首页 > 解决方案 > 如何使用 React Redux Hooks 加载微调器

问题描述

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

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

//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 来挂钩(或)请告诉我如何使用 react-redux 挂钩加载微调器。感谢您的帮助!

标签: reactjsreduxreact-reduxreact-hooks

解决方案


更简单的方法是在动作本身中显示和隐藏加载器。在 promise 之前,将 Loader 设置为 true。然后然后抓住你可以隐藏装载机。

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);
};

推荐阅读