I have got the data from reducer and display it in console
but when i want to access specific object for example (table.nomor) and it become error
this is for my reducer:
export const orderListDetailReducer = (state = { orders: {} }, action) => {
switch (action.type) {
case ORDER_TABLE:
return {
orders: action.payload
}
default:
return state;
}
}
this is for my screen:
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { listOrderDetail } from '../actions/orderAction'
const PlaceOrderScreen = (props) => {
const orderId = props.match.params.id
const orderListDetail = useSelector(state => state.orderListDetail)
const { orders } = orderListDetail
const dispatch = useDispatch()
useEffect(() => {
dispatch(listOrderDetail(orderId))
}, [dispatch, orderId])
console.log(orders.table.nomor);
this is common issue with async behavior on react-redux store, you need to understand useSelector works async and to check the variable with full values you need to use a useEffec, check the following example:
***try the code and tell me how goes:)
import React, { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' import { listOrderDetail } from '../actions/orderAction' const PlaceOrderScreen = (props) => { const orderId = props.match.params.id const orders = useSelector(state => state.orderListDetail.orders)//-->changed this line -->added one level //const { orders } = orderListDetail //-->commented this line const dispatch = useDispatch() useEffect(() => { dispatch(listOrderDetail(orderId)) }, [dispatch, orderId]) //-->create new useEffect and add the dependency from useSelector constant useEffect(() => { console.log('orders',orders); console.log('nomor',orders.table.nomor); }, [orders]);
The first render of your component happens before the dispatched action has completed its update of the store. That means that the value of state
on your first render is the initial value (unless you have already updated the state from some other component).
Your initial state is state = { orders: {} }
so the initial value of orders
is an empty object {}
. You can access orders.table
on the empty object, but the value of orders.table
is undefined
. You cannot access orders.table.nomor
because that would be trying to get the property nomor
from orders.table
which is undefined
-- so you get the error "Cannot read property 'nomor' of undefined".
You need to make sure that your component can render properly at any point in the lifecycle, whether or not the ORDER_TABLE
action has been completed.
You can make sure that orders.table
is not undefined
before accessing the .nomor
property.
const nomor = orders.table ? orders.table.nomor : someDefaultValue;
Or more concisely with optional chaining .
const nomor = orders.table?.nomor; // will be undefined if not able to access
You can set a deeper initial value object for your reducer which allows you to access orders.table.nomor
. This may or may not make sense depending on your app's data structures.
If orders.table
is an empty object {}
instead of undefined
, then it will be ok to access orders.table.nomor
. The value of orders.table.nomor
in this case is undefined
.
const initialState = {
orders: {
table: {}
}
}
You can also go one level deeper and set an initial value for nomor
.
const initialState = {
orders: {
table: {
nomor: someInitialValue
}
}
}
Either way, you would use this as the initial value for your reducer.
export const orderListDetailReducer = (state = initialState, action) => {
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.