React, Redux: Uncaught TypeError: Cannot read properties of undefined (reading 'region') - javascript

I am fetching data (an object) into a redux state and showing into textarea when user clicks on edit:
const regionData = useSelector((state) => state.myReducer.userDetailList.region);
but first time it gives me below error:
Uncaught TypeError: Cannot read properties of undefined (reading 'region')
also this error occurred when i changed code as per eslint suggestion:
i.e.
Use an object spread instead of `Object.assign` eg: `{ ...foo }`
Old Code:
return Object.assign({}, state, {
userDetailList: {
region: action.userDetailsPayload.region,
},
});
New Code:
const userDetailList = {
region: action.userDetailsPayload.region,
};
return { ...state, ...userDetailList };
As a result userDetailList showing as BLANK in Chrome redux-devtool. its working with old code (Object.assign)
I am new to react and redux, so any help is much appreciated. Thanks!

I had a promblem same this one.
Finally I've found out that if I use term "Reducer" or "State" at the end of state's name or reducer's name that are witten by me,
my code runs with error
Uncaught TypeError: Cannot read properties of undefined (reading 'result_201')
my reducer:
export function netInfoRecordReducer (
state = initialStateNetInfoRecord,
action : Actions
) : NetInfoRecordState {
switch (action.type) {
case SET_NET_INFO_RECORD: {
if ( action.payload.RESULT === "SUCCESS") {
return {
...state,
result_201: action.payload.RESULT_CONTENT,
};
}
return state;
}
default:
return state;
}
}
and my index.tsx file for defining CobineReducer and RoutState:
export default combineReducers({
netInfoRecordReducer: netInfoRecordReducer,
});
export interface RootState {
netInfoRecordState: NetInfoRecordState;
}
it runs with that error when I want acceess to the state in another file:
const netInfoRecord = useAppSelector( (state) =>
state.netInfoRecord.result_201);
console.log(netInfoRecord);
but if I remove "State" and "Reducer" term and change my index.tsx file to :
export default combineReducers({
netInfoRecord: netInfoRecordReducer,
});
export interface RootState {
netInfoRecord: NetInfoRecordState;
}
it works now ! :)

Related

NGRX entity updateOne not working: id undefined

I decided to ask for help, I just cannot get my head around NGRX Entity! (This code was created initially by NX ).
I have followed the NGRX Entity guide, I have also looked at loads of tutorial videos but I still cannot get NGRX Entity updateOne to work.
Getting this error below - I can load the entities into the store with no issue, and these are building my UI fine.
I have an Entity collection of buttons and want to update the Store State of a button when clicked - that's all!
(any ideas why this is not working??)
ERROR TypeError: Cannot read property 'id' of undefined
at http://localhost:4200/vendor.js:83815:26
at Array.filter (<anonymous>)
at updateManyMutably (http://localhost:4200/vendor.js:83811:27)
at updateOneMutably (http://localhost:4200/vendor.js:83801:16)
at Object.operation [as updateOne] (http://localhost:4200/vendor.js:83622:27)
at http://localhost:4200/main.js:1169:28
at http://localhost:4200/vendor.js:88532:26
at reducer (http://localhost:4200/main.js:1173:12)
at http://localhost:4200/vendor.js:87072:20
at combination (http://localhost:4200/vendor.js:86960:37)
This is the code I have so far:
// state
export interface QuickButton {
id: number;
isSelected: boolean;
title: string;
linkUrl: string;
}
// in component
this.store.dispatch( actions.setQuickFilter( evt ) );
// evt = {id: 1, isSelected: true, linkUrl: "", title: "Video"}
// in actions
export const setQuickFilter = createAction(
'[QuickBar] setQuickFilter',
props<{update: Update<QuickButton>}>()
);
// in reducer
export const QUICKBAR_FEATURE_KEY = 'quickBar';
export interface State extends EntityState<QuickButton> {
selectedId?: string | number; // which QuickBar record selected
loaded: boolean; // has the QuickBar list been loaded
error?: string | null; // last none error (if any)
}
export interface QuickBarPartialState {
readonly [QUICKBAR_FEATURE_KEY]: State;
}
export const quickBarAdapter: EntityAdapter<QuickButton> = createEntityAdapter<QuickButton>();
export const initialState = quickBarAdapter.getInitialState({
// set initial required properties
loaded: false,
});
const quickBarReducer = createReducer(
initialState,
on(QuickBarActions.loadQuickBarSuccess, (state, action) =>
quickBarAdapter.addAll( action.quickBar, state )
),
on(QuickBarActions.loadQuickBarFailure, (state, { error }) => ({
...state,
error,
})),
on(QuickBarActions.setQuickFilter, (state, {update}) => {
/// **** This is NOT Working *****
return quickBarAdapter.updateOne( update, state);
}
)
);
export function reducer(state: State | undefined, action: Action) {
return quickBarReducer(state, action);
}
export const {
selectIds,
selectEntities,
selectAll,
selectTotal,
} = quickBarAdapter.getSelectors();
You're dispatching your action incorrectly.
this.store.dispatch(actions.setQuickFilter(evt));
should be
this.store.dispatch(actions.setQuickFilter({ update: evt }));
Yay!! finally.
This was a real dumb error - from not understanding Entity.
Lots of trial and error & logging to solve this!
Solution:
Change the dispatch call in component from:
this.store.dispatch( actions.setQuickFilter( {update: evt} } ) );
to:
this.store.dispatch( actions.setQuickFilter( {update: {id: evt.id, changes: evt} } ) );
Now all my subscribed features will be able to use the updated values in the buttons to control their own UI elements. Finally!

React-redux dispatch function with parameters from child component is undefined

I have an action
export const saveNewTask = (taskName, taskDescription) => async dispatch => {
console.log(taskName, taskDescription);
const res = await axios.post('/api/add-new-task', {
taskName,
taskDescription
});
console.log(res);
dispatch({ type: SAVE_TASK, payload: res.data });
};
a parent container that contains a child container which is a Formik form and should allow the child component to save the Formik form contents to the db via the above mentioned action.
import { saveNewTask } from '../actions/index';
class ClientDashboard extends React.Component {
render() {
return <NewTask saveNewTask={saveNewTask()} />;
}
}
export default connect(null, { saveNewTask })(Container);
NewTask.js child component that does not know anything about Redux:
function NewTask(props) {
const formik = useFormik({
initialValues: {
taskName: '',
taskDescription: ''
},
onSubmit: values => {
// alert(JSON.stringify(values, null, 2));
props.saveNewTask(values.taskName, values.taskDescription);
}
});
...
}
but the action never gets the parameters that I am trying to pass through the Formik component (the commented alert line displays both values perfectly) and says both taskName and taskDescription are undefined. Also the dispatch in the last line of the action says
Uncaught (in promise) TypeError: dispatch is not a function at Object.saveNewTask
I think this is more of a syntax error than anything else but any help would be greatly appreciated.
The problem is in this line:
return <NewTask saveNewTask={saveNewTask()} />;
You need to pass a prop for calling the action, not the result of the function call.
You need to call your prop, not your action creator method.
So, change that line to:
return <NewTask saveNewTask={this.props.saveNewTask} />;

Redux initial state disappears on action

I have an initial state in my reducer which is an empty object
const initialState = {
postHistory: {},
loading: true
};
I've noticed that when I run a function from a different component which dispatches the action that this initial state actually disappears. This is causing me problems because in one of my components I'm trying to detect the present of data in this object.
const obj = this.props.postHistory;
this.props.postHistory[Object.keys(obj)[0]] && this.props.postHistory[Object.keys(obj)[0]]
However when the action is fired, I can see in redux that the initial state for the object has completely disappeared and only the loading value is there.
TypeError: Cannot convert undefined or null to object
Has any one else encountered such an issue? Any advice to overcome welcome! Thank you.
Adding reducer code as suggested:
import { POST_HISTORY } from '../actions/types';
const initialState = {
postHistory: {},
loading: true,
};
export default function(state = initialState, action){
const { type, payload } = action;
switch(type){
case POST_HISTORY :
return {
...state,
postHistory: payload.data,
loading: false
}
default:
return state;
}
}
First console your payload.data....then check that the data which you are getting is in "JSON" format our string format..If the data is in "Object" form then it will store in your POSTHISTORY, and if your data is in "json" format then it will not store the data in initial state.

How to fix mapStateToProps from accessing an undefined state key without checking manually?

I am creating a single page web application with React, with the state stored using Redux. When I access something like state.workspace.guest.data in mapStateToProps() it causes an exception crashing the application.
It appears mapStateToProps() is invoked before componentDidMount(), which invokes this.props.getGuests() action that actually causes state.workspace.guest to be initialized. The page loads properly when I manually enter the URL and press enter. However, mapStateToProps() causes an exception when I navigate through the application, with state.workspace.guest being undefined.
A possible solution would be to check if state.workspace.guest is defined. However, I feel there is a better way to do it?
The answers in the following link suggest to use selectors. I am not sure if this is the solution to my problem, given I am new to Redux.
react js mapStateToProps triggers Uncaught TypeError: Cannot read property 'map' of undefined
Here are the mapping functions.
function mapDispatchToProps(dispatch) {
return bindActionCreators({
getGuests: Actions.getGuests
}, dispatch);
}
function mapStateToProps(state, ownProps) {
return {
guests : state.workspace.guest.data
}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(GuestSearchTable));
The componentDidMount() function which actually triggers an action which in turn loads the data.
componentDidMount() {
this.props.getGuests();
}
Here is the reducer.
const initialState = {
data : []
};
function guestReducer(state = initialState, action) {
switch (action.type) {
case Actions.GET_GUESTS: {
return {
...state,
data : action.payload.data
};
}
case Actions.GET_GUEST: {
return {
...state,
guest: action.payload.data
};
}
case Actions.SAVE_GUEST: {
return {
...state,
guest: action.payload.data
};
}
default: {
return state;
}
}
};
I expect the initial value of the state.workspace.guest to be { data : [] }. But the actual value is undefined. The same problem appears in all the other pages.
You are trying to access data from guest key.
function mapStateToProps(state, ownProps) {
return {
guests : state.workspace.guest.data
}
}
I think you want to access state.workspace.data or you have to change key name to guests in reducer and the intialize state as follow:
return {
guests: state.workspace.guests
}

Getting error when setting the whole Ngrx store state to undefined using `Meta Reducers` by help of dispatching logout action

I want to logout from my app and before logging out I want to make sure I have completely cleared my app ngrx store states using MetaReducer with the help of this code
import { StoreModule, ActionReducer, MetaReducer } from '#ngrx/store';
export function logout(reducer: ActionReducer<any>): ActionReducer<any> {
return function (state, action) {
if (action.type === 'LOGOUT') {
state = undefined;
}
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<any>[] = [logout];
when I am inside of a component which is subscribed to one of ngrx store state for example list of invoices, so when I am clicking log out button from here so getting this error in the console
and the line which gives me the error is
this.$invoice.takeWhile(() => this.isComponentAlive).subscribe(
invoice => {
this.permission = this.departmentService.getPermissionOfInvoiceCurrentDepartment(invoice.currentDepartmentId);
}
);
if I am changing the code to this
this.$invoice.takeWhile(() => this.isComponentAlive).subscribe(
invoice => {
if (invoice) {
this.permission = this.departmentService.getPermissionOfInvoiceCurrentDepartment(invoice.currentDepartmentId);
}
}
);
it solves the problem but I have many places like this so I want to one-stop-shop solution for this anyone could help me with this.

Categories

Resources