I dispatching a function using my useEffect to populate my state when the page is mounted. The useEffect is on a infinity loop, even if i put an empty dependency array.
const token = JSON.parse(localStorage.getItem("xibo"));
const access_token = token.access_token;
useEffect(() => {
dispatch(getDisplays(access_token));
}, []);
I already try to put some dependencies but with the same result.
const token = JSON.parse(localStorage.getItem("xibo"));
const access_token = token.access_token;
useEffect(() => {
dispatch(getDisplays(access_token));
}, [access_token, dispatch]);
Any idea how to fix this problem?
this is the full code of the file
import React, { useEffect } from "react";
import { WaveLoading } from "react-loadingg";
import { useDispatch, useSelector } from "react-redux";
import { getDisplays } from "../features/xiboAuth/xiboSlice";
const DisplayList = () => {
const dispatch = useDispatch();
const { isLoading } = useSelector((store) => store.xibo);
const token = JSON.parse(localStorage.getItem("xibo"));
const access_token = token.access_token;
useEffect(() => {
dispatch(getDisplays(access_token));
}, [access_token, dispatch]);
return (
<>
{isLoading ? (
<WaveLoading />
) : (
<div className="container-fluid">
<div className="title_table">
<h3>List of displays</h3>
</div>
<table className="table table-striped">
<thead>
<tr>
<th className="col">#</th>
<th className="col">name</th>
<th className="col">type</th>
<th className="col">ip</th>
</tr>
</thead>
<tbody>
<tr></tr>
</tbody>
</table>
</div>
)}
</>
);
};
export default DisplayList;
this is the file that call this component
import React, { useEffect } from "react";
import { WaveLoading } from "react-loadingg";
import { useDispatch, useSelector } from "react-redux";
import { toast } from "react-toastify";
import DisplayList from "../components/DisplayList";
import { getDisplays, getToken } from "../features/xiboAuth/xiboSlice";
const Dashboard = () => {
const { user } = useSelector((store) => store.auth);
const { isError, message, isLoading, xibo } = useSelector(
(store) => store.xibo,
);
const dispatch = useDispatch();
useEffect(() => {
if (isError) {
toast.error(message);
}
if (user) {
dispatch(getToken());
}
}, [user, isError, message, dispatch]);
return (
<>
{isLoading ? (
<WaveLoading />
) : (
<div className="col py-3">
<div className="d-flex dash_dsp_list">
<DisplayList />
</div>
</div>
)}
</>
);
};
export default Dashboard;
and this is the reducer that the useEffect must call only once.
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import xiboService from "./xiboService.js";
const data = JSON.parse(localStorage.getItem("xibo"));
const initialState = {
xibo: data ? data : null,
displays: null,
isError: false,
isLoading: false,
isSuccess: false,
message: "",
};
export const getToken = createAsyncThunk("xibo/getToken", async (thunkAPI) => {
try {
const response = await xiboService.getAccessToken();
if (response.data.status === 201) {
localStorage.setItem("xibo", JSON.stringify(response.data.data));
}
return response;
} catch (error) {
const message =
(error.response && error.response.data && error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
});
export const getDisplays = createAsyncThunk(
"xibo/getDisplays",
async (data, thunkAPI) => {
try {
return await xiboService.getDisplayList(data);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
},
);
export const xiboSlice = createSlice({
name: "xibo",
initialState,
reducers: {
reset: (state) => {
state.isError = false;
state.isSuccess = false;
state.isLoading = false;
state.message = "";
},
},
extraReducers: (builder) => {
builder
.addCase(getToken.pending, (state) => {
state.isLoading = true;
})
.addCase(getToken.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.xibo = action.payload;
})
.addCase(getToken.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.xibo = null;
})
.addCase(getDisplays.pending, (state) => {
state.isLoading = true;
})
.addCase(getDisplays.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.displays = action.payload;
})
.addCase(getDisplays.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.displays = null;
});
},
});
export const { reset } = xiboSlice.actions;
export default xiboSlice.reducer;
In your first example you said that your useEffect
fires repeatedly even with an empty dependency array. What this means is that your DisplayList
component is being recreated continuously. Obviously the issue is in your Dashboard
component and it would have to be something in the useEffect
.