I am trying to load spinner using react-redux hooks (useSelector and useDispatch). I am able to fetch data but not loader (in my case showLoader and hideLoader)
Expectation: when I click the refresh button I want to load spinner (in background it will refresh the data). Before clicking the button I am able to fetch data using 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>
);
}
This is the component where my spinner resides. I want to fetch this component while loading spinner
//Refresh Component
import React from "react";
export default function Refresh() {
return <div>Spinner....</div>;
}
I saw few examples online, where I found everything is in class components
// 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>
Can somebody help me how to convert the above class to functional based component and instead of using mapStateToProps to hooks (or) please tell me how to load the spinner using react-redux hooks. I appreciate the help!