简体   繁体   中英

cannot access object from react-redux

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

Problem: undefined in initial state

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.

Solution 1: guarded access

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

Solution 2: initial value

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM