I am having front-end issues with Redux. The backend API is working correctly with Postman so I know the problem isn't there and for some reason I can't get the data in my Redux store to populate.
It is my first createAsyncThunk passing the userId to the backend so I know the problem is something to do with that. I have a console.log in my backend API that prints the log whenever it is accessed so I can see that it isn't being accessed. In the Redux store I am getting a rejected message so I think it is something to do with that.
Can anyone see anything in my action that looks out of place?
Form useEffect
const userDiveLog = useSelector(state => state.user.userDiveLog);
useEffect(() => {
dispatch(fetchUserDiveLog(user.userID));
}, []);
createAsyncThunk
export const fetchUserDiveLogs = createAsyncThunk(
'diveLog/requireUserData', // action name
// action expects to be called with the name of the field
async (userId, userDiveLogList) => {
// you need to define a function to fetch the data by field name
const response = await userDiveLogList.fetchById(userId);
const { data } = response;
// what we return will be the action payload
return {
userDiveLog: data,
// items: data
};
},
// only fetch when needed: https://redux-toolkit.js.org/api/createAsyncThunk#canceling-before-execution
{
condition: (userDiveLog, {getState}) => {
const {userDiveLogs} = getState();
// check if there is already data by looking at the array length
if ( userDiveLogs[userDiveLog].length > 0 ) {
// return false to cancel execution
return false;
}
}
}
)
service
export const userDiveLogList = (userId) => {
return axios.get(API_URL + `userdiveloglist/${userId}`);
};
reducer
export const userSlice = createSlice({
name: 'user',
initialState: {
dives: [],
diveSpots: [],
articles: [],
userDiveLog: []
},
reducers: {
// picks up the pending action from the thunk
[fetchUserDiveLogs.pending.type]: (state) => {
// set didLoadData to prevent unnecessary re-fetching
state.didLoadData = true;
},
// picks up the success action from the thunk
[fetchUserDiveLogs.fulfilled.type]: (state, action) => {
// want to replace all lists, there are multiple ways to do this
// I am returning a new state which overrides any properties
return {
...state,
...action.payload
}
},
createAsyncThunk
only accepts a single argument for your thunks / payload creation callbacks. You're currently declaring that it takes two arguments: (userId, userDiveLogList)
. You would need to put both of these together into a single object.
Beyond that, there's really no reason to pass userDiveLogList
in as a parameter, unless you're overly concerned about mocking API calls (in which case you could consider using the "extra argument" option for the thunk middleware to inject an API layer). I would just declare that above the call to createAsyncThunk()
, or import it from another file, and access it that way.