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

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

Related

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.

React Redux form with connect()?

i am trying to build a react redux form using the connect() instead useSelector and useDispatch.
I managed to display the list of data and to reset the forms. But i didn't manage to send data. Here is the code:
Reducer.js
const initialState = {
tasks: {
name: "",
age: "",
job: "",
},
list: [
{
id: 0,
name: "Maillard",
age: 35,
job: "soldier",
},
],
};
export const toDoReducer = (state = initialState, action) => {
switch (action.type) {
case "name":
return {
...state,
tasks: {
name: action.payload,
},
};
case "age":
return {
...state,
tasks: {
age: action.payload,
},
};
case "job":
return {
...state,
tasks: {
job: action.payload,
},
};
case "clear":
return {
...state,
tasks: {
name: "",
age: "",
job: "",
},
};
case "add":
return {
...state,
tasks: {
...state.tasks,
id: state.list.length + 1,
},
};
default:
return {
...state,
};
}
};
export default toDoReducer;
import React from "react";
import { connect } from "react-redux";
import {
setName,
setAge,
setJob,
clearForm,
addForm,
} from "../../redux/action";
export const Form = (props) => {
return (
<div>
Name
<input value={props.list.name} onChange={(e) => { props.Name(e.target.value) }} />
Age
<input value={props.list.age} onChange={(e) => { props.Age(e.target.value) }} />
Profession
<input value={props.list.job} onChange={(e) => { props.Job(e.target.value) }} />
<div style={{ padding: 20 }}>
<button onClick={props.Clear}>Reset</button>
<button onClick={props.Add}>Envoyer</button>
</div>
</div>
);
};
const mapDispatchToProps = (dispatch) => {
return {
Name: () => {
dispatch({
type: "name",
setName,
});
},
Age: () => {
dispatch({ type: "age", setAge });
},
Job: () => {
dispatch({
type: "job",
setJob,
});
},
Clear: () => {
dispatch({ type: "clear", clearForm, });
},
Add: () => {
dispatch({)}
// My problem comes from the Add
<!-- begin snippet: js hide: false console: true babel: false -->
type: "add",
addForm
})
}
};
};
const mapStateToProps = (state) => ({
list: state.tasks,
});
export default connect(mapStateToProps, mapDispatchToProps)(Form);
// export default Form;
My problems comes from in mapDispatchToProps, i don't know what to do for the function Add
Your actions should be the ones defining the action type and you should call them in the mapDispatchToProps, not pass them as part of the action.
So your addForm should be something like
const addForm = () => ({
type:'add'
});
and in your mapDispatchToProps it should be like
Add: () => dispatch(addForm()),
But you have the same problem with all your dispatching
for example the Name should be
action
const setName = (payload) => ({
type:'name',
payload
});
mapDispatchToProps
Name: (nameValue) => {
dispatch(setName(nameValue));
},

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

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];
},
},
});

How to update state in react-native to detect when a certain event(given date has passed) has occurred with Hooks?

I am using react-native with redux.
I want to update the state in my contacts when their dueDate has passed and this is my code
This is the way I am updating state in App.js
useEffect(()=>{
setInterval(()=>{
updateContacts(contacts.map(item => item.dueDate < new Date()
?
( d=new Date(item.dueDate),
item.payments.duration=='year'?d.setMonth(d.getMonth()+12)
:item.payments.duration=='hyear'? d.setMonth(d.getMonth()+6)
:item.payments.duration=='month'?d.setMonth(d.getMonth()+1)
:d.setDate(d.getDate() +7),
balance=item.balance-item.payments.payment,
{
...item,dueDate:d,balance
})
:item)
)
},60000)
},[]);
const mapStateToProps=(state)=>{
return{
contacts:state.contactReducer.contacts
}
}
const mapDisptachToProps=(dispatch)=>{
return {
addContact: (contact) => dispatch(addContact(contact)),
updateContacts: (contacts)=> dispatch(updateContacts(contacts))
}
}
export default connect(mapStateToProps,mapDisptachToProps) (App);
My contact.Reducer
const initialState={
contacts:
[
{
id: uuid.v4(),
name: {firstName: 'Neelanshu', lastName: 'Garg'},
contact: {
Mobile: '8800170377',
Alt: '',
email: 'neelanshugarg097#gmail.com',
},
payments: {
paid: 0,
duration: 'month',
payment: 1000,
},
balance: 8800,
date: new Date(2021, 10, 8),
dueDate:new Date(2021,10,15),
},
{
id: uuid.v4(),
name: {firstName: 'Neel', lastName: 'Garg'},
contact: {
Mobile: '8800170377',
Alt: '',
email: 'neelanshugarg097#gmail.com',
},
payments: {
paid: 0,
duration: 'week',
payment: 100,
},
balance: -100,
date: new Date(2021, 10, 8),
dueDate:new Date(2021,10,15),
},
{
id: uuid.v4(),
name: {firstName: 'shu', lastName: 'Garg'},
contact: {
Mobile: '8800170377',
Alt: '',
email: 'neelanshugarg097#gmail.com',
},
payments: {
paid: 0,
duration: 'week',
payment: 100,
},
balance: 8800,
date: new Date(2021, 10, 8),
dueDate:new Date(2021,10,15),
}
]
}
const contactReducer= (state=initialState, action)=>{
switch(action.type)
{
case ADD_CONTACT:
return{
...state,
contacts:[...state.contacts,{id: uuid.v4(), ...action.data}]
};
case DELETE_CONTACT:
return {
...state,
contacts:state.contacts.filter(item => item.id != action.id)
};
case UPDATE_CONTACTS:
console.log(action.data)
return {
...state,
contacts:action.data
}
default:
return state;
}
}
export default contactReducer;
This is store.js
import {createStore, combineReducers} from 'redux'
import contactReducer from './reducers/contactReducer';
import devToolsEnhancer from 'remote-redux-devtools';
const rootReducer= combineReducers({
contactReducer: contactReducer
})
const configureStore = ( ) => createStore(rootReducer,devToolsEnhancer({realtime:true,host: 'localhost',
port: 8000
}));
export default configureStore;
So problem is when I add a new contact(through action.type== ADD_CONTACT) it gets shown in the state and UI for some time but after update state goes back to initial hardcoded state and the new added contact goes away. I cant figure out how to update my state at all.
If I remove the update for state the new contact stays in the state and shown in UI all time.
Please Help

Resources