I fetched an array and want to add it to my state - reactjs

I fetched an array of objects but can't add (or replace) them to state.
const searchSlice = createSlice({
name: 'search',
initialState: [],
reducers: {
getResults(state, action) {
state = action.payload;
},
},
});
I tried "state.push(action.payload)" but it turned out a nested array. "action.payload" is the right response.

Since pushing it into the state creates a nested array,
For replacing, try
const searchSlice = createSlice({
name: 'search',
initialState: [],
reducers: {
getResults(state, action) {
return [...action.payload];
},
},
});
For adding, try
const searchSlice = createSlice({
name: 'search',
initialState: [],
reducers: {
getResults(state, action) {
return [...state, ...action.payload];
},
},
});

Related

Mutate one value in redux toolkit

i canĀ“t wrap my head around changing one single value in my redux store.
I am story data in my redux store with writeItems reducer.
{
"val1": true,
"val2": false,
"val3": false,
"val4": true, <-
"val5": true,
"val6": false,
}
export const itemsSlice = createSlice({
name: "items",
initialState,
reducers: {
writeItems: (state, action) => {
return { ...state, items: [...action.payload] };
},
updateItem: (state, action) => {
return {...state, ...action.payload}
},
},
});
Now I am trying to mutate a single value in this object (e.g val4) with the updateItem reducer but it creates only a new object with only the new property in my store.
dispatch(updateItem([{ val4: false }]));
{
"val4": false,
}
How is it possible to get this object?
{
"val1": true,
"val2": false,
"val3": false,
"val4": false, <-
"val5": true,
"val6": false,
}

extraReducers -> builder.addCase() typescript error (Redux Toolkit)

I am new to using RTK and typescript and I have a problem with (Property 'pending' does not exist on type '() => Promise >') in my extraReducers. I don't see any similar situation online as mine and suspect I am missing something very simple. However, I can't seem to find it.
It's my axios api call function:
export const getUser = () =>
apiCallWithAuthToken.get<UserResponse>("users/me");
My AsyncThunk:
export const getUserData = createAsyncThunk(
"user/getUser", async () => {
const response = await getUser();
return response.data;
}
);
Types and initial state:
interface userState {
id: string;
walletAddress: string;
email: string;
firstName: string;
lastName: string;
reflink: string;
createdAt: string;
modifiedAt: string;
isLogged: boolean;
loading: boolean;
}
const initialState: userState = {
id: "",
walletAddress: "",
email: "",
firstName: "",
lastName: "",
reflink: "",
createdAt: "",
modifiedAt: "",
isLogged: false,
loading: false
};
it's my store:
import { configureStore } from "#reduxjs/toolkit";
import userSlice, { getUserData } from "./features/user/userSlice";
export const store = configureStore({
reducer: {
user: userSlice,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: {
extraArgument: getUserData,
},
serializableCheck: false,
}),
})
and it's my slice:
export const userSlice = createSlice({
name: "user",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getUser.pending, (state) => {
state.loading = true;
})
}
});
export default userSlice.reducer;
I got a typescript error, why? Error image below:error image

Redux How to insert new Sub data in state

I'm making a todo app and using redux for state management. My todo state is made up of nested arrays.
const initialState = {
todos: [
{
id: 1,
name: "task1",
subdata: [
{
id: 101,
name: "subtask1",
complete: false,
},
{
id: 102,
name: "subtask2",
complete: true,
},
],
},
{
id: 2,
name: "task2",
subdata: [
{
id: 103,
name: "subtask3",
complete: false,
},
{
id: 104,
name: "subtask4",
complete: true,
},
],
},
Reducers:
export default function reducer(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
const newTodo = state.todos.concat(action.payload);
return { ...state, todos: newTodo };
case ADD_SUBTODO:
const newSubtodo = action.payload;
?????????????????????????????????????????????
How can i append new subtodo to initialstate?
I used the immer library, but I want to do it the traditional way, for example the spread operator. I would be glad if you help.
You could do something like...
// send payload as {id:1,newSubtodo: newSubtodo}
case ADD_SUBTODO:
const newSubtodo = action.payload.newSubtodo;
//id is the task/todo id of which you want to add a new subdata
const newTask = initialState.todos.find(i=>i.id==action.payload.id)
//id is the task/todo id of which you want to add a new subdata
newTask.subdata.push(newSubtodo)
return {...initialState,todos:[...initialState.todos,newTask]}
Note: Using nested objects as state in React Js is not a good
practice.

Mutate state with dynamic keys in CreateSlice method

I am using Redux Toolkit in my application, where I want to update state with dynamic keys(state[keys]). I am getting error as Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'RootFormState'
For example:
//someSlice.ts
interface FormState<T> {
isValid: boolean;
answer: T;
}
interface RootFormState {
breakfast: FormState<Array>;
lunch: FormState<string>;
dinner: FormState<Array>;
}
const initialState:RootFormState = {
breakfast: {
isValid: false,
answer: []
},
lunch: {
isValid: false,
answer: ""
},
dinner: {
isValid: false,
answer: []
}
}
const foodSlice = createSlice({
name: 'food',
initialState,
reduce: {
updateAnswer: (state, action) => {
const {id, answer} = action.payload;
state[id].answer = answer;
}
}
})
RTK exports a PayloadAction type you can use it to type the action parameter of the reducer.
import { createSlice, PayloadAction } from '#reduxjs/toolkit';
interface FormState<T> {
isValid: boolean;
answer: T;
}
interface RootFormState {
breakfast: FormState<Array<string>>;
lunch: FormState<string>;
dinner: FormState<Array<string>>;
}
const initialState: RootFormState = {
breakfast: { isValid: false, answer: [] },
lunch: { isValid: false, answer: '' },
dinner: { isValid: false, answer: [] },
};
type ValueOf<T> = T[keyof T];
const foodSlice = createSlice({
name: 'food',
initialState,
reducers: {
updateAnswer: (
state,
action: PayloadAction<{ id: keyof RootFormState; answer: ValueOf<RootFormState>['answer'] }>,
) => {
const { id, answer } = action.payload;
state[id].answer = answer;
},
},
});

Which reducer gets used when using dispatch in mapDispatchToProps? [duplicate]

This question already has answers here:
All reducers will be invoked when an action is dispatched?
(3 answers)
Closed 2 years ago.
I am learning about Redux and I have two reducers, a contactReducer to show contacts on the page and a testReducer to just mess around with. In one of my component files I have this function:
const mapDispatchToProps = (dispatch) => ({
getContacts: () => dispatch({ type: "TEST_ACTION" }),
});
These are my two reducer files:
contactReducer:
import { GET_CONTACTS } from "../actions/types";
const initialState = {
contacts: [
{
id: 1,
name: "John Doe",
email: "john#gmail.com",
phone: "555-555-5555",
},
{
id: 2,
name: "Karen Williams",
email: "karen#gmail.com",
phone: "444-444-4444",
},
{
id: 3,
name: "Henry Johnson",
email: "henry#gmail.com",
phone: "333-333-333",
},
],
};
export default function (state = initialState, action) {
switch (action.type) {
case GET_CONTACTS:
return {
...state,
};
default:
console.log("testing action in contactReducer");
return state;
}
}
and testReducer:
import { GET_CONTACTS } from "../actions/types";
const initialState = {
contactsTest: [
{
id: 1,
name: "ffffffffffff",
email: "john#gmail.com",
phone: "555-555-5555",
},
{
id: 2,
name: "ggggggggggggg",
email: "karen#gmail.com",
phone: "444-444-4444",
},
{
id: 3,
name: "aaaaaaaaaaaaaa",
email: "henry#gmail.com",
phone: "333-333-333",
},
],
};
export default function (state = initialState, action) {
switch (action.type) {
case "TEST_ACTION":
return {
...state,
};
default:
console.log("testing action");
return state;
}
}
So, what I noticed from the console.log statements in the reducer files was that for every contact, both the contactReducer and testReducer's function was called with this line:
getContacts: () => dispatch({ type: "TEST_ACTION" }),
});
What if I have multiple reducers but I only want to call one of their functions for dispatch, what would I do?
combineReducers, Is a helper function in redux that helps you divide your reducers. take a look at this link: LINK

Resources