I'm trying to fetch a list from database and add to my state. but the action.payload is undefined on the api the result is correct.
mySlice
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import { fileFetch } from "./fileAPI";
const initialState = {
loading: "idle" | "pending" | "succeeded" | "failed",
error: false,
filesUploaded: null,
};
export const fetchFiles = createAsyncThunk("files/fetchFiles", () => {
return fileFetch();
});
export const fileSlice = createSlice({
name: "files",
initialState,
reducers: {},
extraReducers(builder) {
builder
.addCase(fetchFiles.pending, (state, action) => {
state.loading = "pending";
})
.addCase(fetchFiles.fulfilled, (state, action) => {
console.log(action);
state.loading = "succeeded";
state.filesUploaded = action.payload;
})
.addCase(fetchFiles.rejected, (state, action) => {
state.loading = "failed";
state.filesUploaded = [];
state.error = action.error.message;
});
},
});
export default fileSlice.reducer;
myAPI
const api = axios.create({
baseURL: "http://localhost:8081/file/",
headers: {
"content-type": "application/json",
},
});
export const fileFetch = async () => {
await api
.get("getAll")
.then((res) => {
console.log(res.data);
return res.data;
})
.catch((err) => {
throw new Error(err);
});
};
the console.log on the api is returning the correct data.
any idea why the payload is undefined?
thanks.
Might be because you are using both async-await and Promise methods in fileFetch function. Try updating it to this
export const fileFetch = async () => {
const response = await api.get("getAll")
return response.data
};
myApi
export const fileFetch = () => api.get("getAll")
mySlice
export const fetchFiles = createAsyncThunk(
"files/fetchFiles",
async ({ rejectWithValue }) => {
try {
const response = await fileFetch();
return response.data;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
Also working lifecycle methods
Related
I have a async action name editLoginIdData() in loginsIdSlice.js,
which i am dispatching from certain component, which edits the data in mongoDB database, then when the action is fullfilled, i mutate the state in extraReducers
editLoginIdData.fulfilled.
But now what i want to do that whenever the editLoginIdData action is fullfilled
i want to also add the updated(which i will get from server responese -> updatedData at editLoginIdData()) data to activitiesData state, which i am handling in activitiesSlice.js
So basically is there a way that when editLoginIdData action is fullfilled we can
dispatch somehow mutate the state in other slice.
One approach i have taken is to import the editLoginIdData() action in activitiesSlice.js and then creating a extraReducer with editLoginIdData.fullfilled
and mutating activitiesData state.
I have done the above approach and seems its working correctly.
But there is a catch, like how show i get the response data at editLoginIdData()
to passed to activitiesSlice.js because i will required that updated data.
if the above appraoch is not correct, then how should i do it
loginsIdSlice.js
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import * as api from "../../api"
const initialState = {
loginsIdData: [],
}
export const fecthLoginIdsData = createAsyncThunk("loginIds/fetch", async ({ user_id }, { getState }) => {
const res = await api.fetchUserLoginIds(user_id);
console.log(res);
const { data } = res;
data.reverse();
return data;
});
export const addNewLoginIdData = createAsyncThunk("loginIds/add", async ({ data, user_id }, { getState }) => {
const res = await api.addNewLoginIdA(data, user_id)
const { loginIdsArray } = res.data;
return loginIdsArray[loginIdsArray.length - 1];
});
export const editLoginIdData = createAsyncThunk("loginIds/edit", async ({ updatedData, login_id }, { getState }) => {
const res = await api.editLoginId(login_id, updatedData);
// console.log(updatedData);
return updatedData;
});
export const deleteLoginData = createAsyncThunk("loginIds/delete", async ({ login_id, user_id }, { getState }) => {
const res = await api.deleteLoginId(login_id, user_id);
// console.log(res);
const { data } = res;
// console.log(data);
return data.reverse();
});
//* Slice
const loginsIdSlice = createSlice({
name: 'loginsId',
initialState: initialState,
extraReducers: (builder) => {
builder.
addCase(fecthLoginIdsData.fulfilled, (state, action) => {
return {
...state,
loginsIdData: action.payload
};
}).
addCase(addNewLoginIdData.fulfilled, (state, action) => {
return {
...state,
loginsIdData: [action.payload, ...state.loginsIdData]
};
}).
addCase(editLoginIdData.fulfilled, (state, action) => {
const newArray = state.loginsIdData.map((loginId) => {
if (loginId._id === action.payload._id) {
return action.payload;
} else {
return loginId;
}
});
return {
...state,
loginsIdData: newArray,
};
}).
addCase(deleteLoginData.fulfilled, (state, action) => {
return {
...state,
loginsIdData: action.payload
};
})
}
})
export const { deleteLoginId, editLoginId } = loginsIdSlice.actions;
export default loginsIdSlice.reducer;
activitiesSlice
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import * as api from "../../api"
import { editLoginIdData } from "../loginsId/loginsIdSlice"
const initialState = {
activitiesData: [],
}
const activitiesSlice = createSlice({
name: 'activities',
initialState: initialState,
extraReducers: (builder) => {
builder.
addCase(editLoginIdData.fullfilled, (state, action) => {
console.log("ss")
return {
...state,
activitiesData: []
};
})
}
})
export default activitiesSlice.reducer;
Is there a way that when editLoginIdData action is fullfilled we can
dispatch somehow mutate the state in other slice.
In my fullfilled i am getting response as undefined. any one please help?
code :
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import axios from "axios";
const fetchPost = createAsyncThunk('fetch/post', async (params: string) => {
try {
const { data } = await axios.get('https://registry.npmjs.org/-/v1/search', { params: { text: params } })
data.objects.map((result: any) => {
console.log('result', result)//getting result
return result.package.name;
});
} catch (err: any) {
return err?.response;
}
})
interface RepositoriesState {
loading: boolean;
error: string | null;
data: string[];
}
const initialRepoState:RepositoriesState = {
loading: false,
error: null,
data:[]
}
const repositorySlice = createSlice({
name: 'repo-slice',
initialState: initialRepoState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchPost.pending, (state) => {
state.loading = true
})
.addCase(fetchPost.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
console.log('payload', action.payload) //undefined
})
.addCase(fetchPost.rejected, (state) => {
state.loading = false;
state.error = "error in api";
state.data = [];
})
}
})
export { fetchPost };
export default repositorySlice.reducer;
Nothing is getting returned from your function... so its undefined
I guess it should be as so
const fetchPost = createAsyncThunk('fetch/post', async (params: string) => {
try {
const { data } = await axios.get('https://registry.npmjs.org/-/v1/search', { params: { text: params } })
return data.objects.map((result: any) => {
console.log('result', result)//getting result
return result.package.name;
});
} catch (err: any) {
return err?.response;
}
})
I'm trying to achieve automated refetching without using RTK Query.
I.e. im writing my API calls using createAsyncThunk & Axios.
On create(post) or update(patch) request being successful, I would rather just "refetch" data, rather than push my changes into the original data set.
This is how it would be done with RTK Query:https://redux-toolkit.js.org/rtk-query/usage/automated-refetching
By invalidating the data.
A simple solution would be if I could call my "fetchClients" thunk..
Any ideas?
import { createSlice, createAsyncThunk, current } from "#reduxjs/toolkit/";
import axios from "axios";
import { getAxiosHeaders } from "../Api/apiHelper";
const initialState = {
clients: [],
client: null,
status: "idle", //'idle' | 'loading' | 'succeeded' | 'failed'
error: null,
isModalOpen: false,
};
export const fetchClients = createAsyncThunk("clients/fetchClients", async () => {
alert("hello fetch clients");
const response = await axios.get(CLIENTS_URL, { headers });
return response.data.clients;
});
export const addNewClient = createAsyncThunk("clients/addNewClient", async (body) => {
const response = await axios.post(CLIENTS_URL, body, { headers });
return response.data;
});
export const clientsSlice = createSlice({
name: "clients",
initialState,
reducers: {
toggleModal: (state, action) => {
state.isModalOpen = !action.payload;
},
},
},
extraReducers: (builder) => {
builder
.addCase(fetchClients.pending, (state, action) => {
state.status = "loading";
})
.addCase(fetchClients.fulfilled, (state, action) => {
state.status = "success";
state.clients = action.payload;
})
.addCase(fetchClients.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
})
.addCase(addNewClient.fulfilled, (state, action) => {
console.log(state.clients);
// REFETCH DATA i.e. fetchClients()
// state.clients.push(action.payload);
})
},
});
export const { clientAdded, toggleModal, setClient } = clientsSlice.actions;
export default clientsSlice.reducer;
I am using react with redux tookit to call my api and store my response in the state, but whenever i am calling the async thunk i am getting undefined in response but i am log my response in api, i am getting the expected response, i didn't know as i am beginner in redux, can anybody please help me what i am doing wrong.
below is my memory slice reducer
import { RecentPublishedApi } from "../../components/api/api";
export const fetchMemoryAsync = createAsyncThunk(
"memory/recentPublishedApi",
async (obj) => {
const response =await RecentPublishedApi(obj);
console.log("i am inside the thunk",response)
return response;
}
);
const initialState = {
data: [],
status: "",
};
export const MemorySlice = createSlice({
name: "memory",
initialState,
reducers: {
},
extraReducers: {
[fetchMemoryAsync.pending]: (state) => {
state.status = "loading";
},
[fetchMemoryAsync.fulfilled]: (state, action) => {
console.log("fulfilled")
state.status = "idle";
console.log(action)
state.data=action.payload;
},
[fetchMemoryAsync.rejected]: (state, action) => {
state.status = "failed";
state.error = action.payload;
},
},
});
// export const { addData } = MemorySlice.actions;
export const selectData = (state) => state.memory.data;
export default MemorySlice.reducer;
my code sandbox link-
https://codesandbox.io/s/hidden-snowflake-px34f?file=/src/App.js
You are not returning anything from your RecentPublishedApi. Add a return statement.
Also, that Promise you build there is already a promise, no need to wrap that manually.
import axios from "axios";
export const RecentPublishedApi = async (data) => {
const headers = {
"Content-Type": "application/json",
"X-CSRF-TOKEN": "e7lwcn_OBGJuu2QsIA8auXzsvi9RGlzueRGDDwVsSKU"
};
return axios
.post("https://public.cuebackqa.com/api/timeline/list", data, {
headers: headers
})
};
Hi first post here so please go easy with me. I new to redux and wondered why im not get a rerender when my store is being updated successfully.
here is my reducer
const initialState = {
pending: false,
loadPlanning: [],
error: null
}
export const loadPlanningReducer = (state = initialState, action) => {
if (action.type === INITIALISE_LOAD_PLANNING_PENDING) {
return {
...state,
pending: true
}
}
if (action.type === INITIALISE_LOAD_PLANNING_SUCCESS) {
console.log('updating state');
return Object.assign({}, state, {
...state,
pending: false,
loadPlanning: state.loadPlanning.concat(action.loadPlanning.items)
});
}
if (action.type === INITIALISE_LOAD_PLANNING_ERROR) {
return {
...state,
pending: false,
error: action.error
}
}
return state;
}
export default loadPlanningReducer;
export const getLoadPlanning = (state) => { console.log('reducer state',state); return state.loadPlanning };
export const getLoadPlanningPending = (state) => state.pending;
export const getLoadPlanningError = (state) => state.error;
The view looks like
const mapStateToProps = (state, ownProps) => ({
error: getLoadPlanningError(state),
loadPlanning: getLoadPlanning(state),
pending: getLoadPlanningPending(state),
options: state.options.options,
option: state.options.currentOption,
oidc: state.oidc
})
const mapDispatchToProps = (dispatch) => {
return {
dispatch
};
}
const fetchLoadPlanning = async (props) => {
props.dispatch(initialiseLoadPlanning());
const httpOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${xxxxxxxx}`
}
};
fetch('/Api/Planning/Get_Data?' + "database=xxxxxx", httpOptions)
.then(res => res.json())
.then(res => {
if (res.hasError) {
throw res.error;
}
props.dispatch(initialiseLoadPlanningSuccess(res.data));
return res.data;
})
.catch(error => {
props.dispatch(initialiseLoadPlanningError(error));
});
}
const LoadPlanningList = (props) => {
useEffect(() => {
fetchLoadPlanning(props);
}, [])
useEffect(() => {
console.log('props changed',props);
},[props])
}
The console log of props changed happens on change of props.pending but not on the dispatch of props.dispatch(initialiseLoadPlanningSuccess(res.data));
console log
You help and wisdom would be most helpful, thanks in advance