【问题标题】:React+Redux:TypeError: Cannot read property 'address' of nullReact+Redux:TypeError:无法读取 null 的属性“地址”
【发布时间】:2021-05-10 20:18:46
【问题描述】:

我是新来的反应。现在我面临一个问题。我的应用程序运行良好(一个简单的电子商务)。当我输入送货地址时,它运行良好。但问题是当我从帐户注销并在发货页面重新登录时,它会显示这样的错误,

TypeError:无法读取 null 的属性“地址”

我正在使用 redux。所以当我从浏览器 Localstorage 中删除现有地址时,它运行良好。Error Showing

ShippingScreen.js

import React,{useState,useEffect} from 'react'
import { Form,Button } from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import FormContainer from '../components/FormContainer'
import { saveShippingAddress } from '../actions/cartActions'
import CheckoutSteps from '../components/CheckoutSteps'

function ShippingScreen({history}) {
    
    const cart = useSelector(state => state.cart)
    const { shippingAddress } = cart
    
    const dispatch = useDispatch()
    
    const [address, setAddress] = useState(shippingAddress.address)
    const [phone, setPhone] = useState(shippingAddress.phone)
    const [city, setCity] = useState(shippingAddress.city)
    const [postalCode, setPostalCode] = useState(shippingAddress.postalCode)
    const [country, setCountry] = useState(shippingAddress.country)
    
    const submitHandler = (e) =>{
        e.preventDefault()
        dispatch(saveShippingAddress({ address,phone,city,postalCode,country }))
        history.push('/payment')
    }
    
    return (
        <FormContainer>
            <CheckoutSteps step1 step2 />
            <h1>Shipping Information</h1>
            <Form onSubmit={submitHandler}>
            
            <Form.Group controlId='address'>
                    <Form.Label>Address</Form.Label> 
                    <Form.Control
                        required
                        type='text'
                        placeholder='Enter Address'
                        value={address ? address : ''}
                        onChange={(e)=> setAddress(e.target.value)}>                    
                    </Form.Control>
                </Form.Group>
                
                <Form.Group controlId='phone'>
                    <Form.Label>Phone Number</Form.Label> 
                    <Form.Control
                        required
                        type='number'
                        placeholder='Enter Phone Number'
                        value={phone ? phone : ''}
                        onChange={(e)=> setPhone(e.target.value)}>                    
                    </Form.Control>
                </Form.Group>
                
                <Form.Group controlId='city'>
                    <Form.Label>City</Form.Label> 
                    <Form.Control
                        required
                        type='text'
                        placeholder='Enter City'
                        value={city ? city : ''}
                        onChange={(e)=> setCity(e.target.value)}>                    
                    </Form.Control>
                </Form.Group>
                
                <Form.Group controlId='postalCode'>
                    <Form.Label>Post Code</Form.Label> 
                    <Form.Control
                        required
                        type='number'
                        placeholder='Enter Post Code'
                        value={postalCode ? postalCode : ''}
                        onChange={(e)=> setPostalCode(e.target.value)}>                    
                    </Form.Control>
                </Form.Group>
                
                <Form.Group controlId='country'>
                    <Form.Label>Country</Form.Label> 
                    <Form.Control
                        required
                        type='text'
                        placeholder='Enter Country'
                        value={country ? country : ''}
                        onChange={(e)=> setCountry(e.target.value)}>                    
                    </Form.Control>
                </Form.Group>
                
                <Button type='submit' variant='primary'>
                    Coninue
                </Button>
            
            </Form>
        </FormContainer>
    )
}

export default ShippingScreen

cartReducer.js

import { CART_ADD_ITEM, 
         CART_REMOVE_ITEM,
         CART_SAVE_SHIPPING_ADDRESS,
        
         CART_SAVE_PAYMENT_METHOD
         } from '../constants/cartConstants'

export const cartReducer = (state={ cartItems:[], shippingAddress: {} },action) =>{
    
    switch (action.type){
        case CART_ADD_ITEM:
            const item=action.payload
            const existItem=state.cartItems.find(x=>x.product===item.product)
            
            if(existItem){
                return{
                    ...state,
                    cartItems: state.cartItems.map(x=>
                                                   x.product === existItem.product ? item : x
                                                )
                }
            }else{
                return{
                    ...state,
                    cartItems:[...state.cartItems, item]
                }
            }
            
        case CART_REMOVE_ITEM:
            return{
                ...state,
                cartItems:state.cartItems.filter(x => x.product !== action.payload)
            }
            
        case CART_SAVE_SHIPPING_ADDRESS:
            return{
                ...state,
                shippingAddress: action.payload
            }
            
        case CART_SAVE_PAYMENT_METHOD:
            return{
                ...state,
                paymentMethod: action.payload
            }
            
        default:
            return state
    }
    
}

cartAction.js

import axios from 'axios'
import { CART_ADD_ITEM, 
         CART_REMOVE_ITEM,
         CART_SAVE_SHIPPING_ADDRESS,
         
         CART_SAVE_PAYMENT_METHOD,
          } from '../constants/cartConstants'

export const addToCart = (id, qty) => async (dispatch, getState)=>{
    const {data} =await axios.get(`http://127.0.0.1:8000/api/products/${id}`)
    
    dispatch({
        type:CART_ADD_ITEM,
        payload:{
            product: data._id,
            name: data.name,
            image: data.image,
            price: data.price,
            countInStock: data.countInStock,
            qty
        }
    })
    
    localStorage.setItem('cartItem' , JSON.stringify(getState().cart.cartItems))
}


export const removeFromCart = (id)=>(dispatch, getState) => {
    dispatch({
        type:CART_REMOVE_ITEM,
        payload:id,
    })
    
    localStorage.setItem('cartItem' , JSON.stringify(getState().cart.cartItems))
}

export const saveShippingAddress = (data)=>(dispatch) => {
    dispatch({
        type:CART_SAVE_SHIPPING_ADDRESS,
        payload:data,
    })
    
    localStorage.setItem('shippingAddress' , JSON.stringify(data))
}

export const savePaymentMethod = (data)=>(dispatch) => {
    dispatch({
        type:CART_SAVE_PAYMENT_METHOD,
        payload:data,
    })
    
    localStorage.setItem('paymentMethod' , JSON.stringify(data))
}

store.js

import { createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import { productListReducers,productDetailsReducers } from './reducers/productReducers';
import { cartReducer } from './reducers/cartReducers'
import { userLoginReducer, userRegisterReducer, userDetailsReducer, userUpdateProfileReducer } from './reducers/userReducers'
import { orderCreateReducer } from './reducers/orderReducers'
const reducer = combineReducers({
    productList: productListReducers,
    productDetails: productDetailsReducers,
    cart: cartReducer,
    userLogin: userLoginReducer,
    userRegister: userRegisterReducer,
    userDetails:userDetailsReducer,
    userUpdateProfile:userUpdateProfileReducer,
    orderCreate:orderCreateReducer,
    
})

const cartItemsFromStorage = localStorage.getItem('cartItems') ? 
    JSON.parse(localStorage.getItem('cartItems')) : []
    
const userInfoFromStorage = localStorage.getItem('userInfo') ? 
    JSON.parse(localStorage.getItem('userInfo')) : null
    
const shippingAddressFromStorage = localStorage.getItem('shippingAddress') ? 
    JSON.parse(localStorage.getItem('sgippingAddress')) : {}

const intitialState = {
    cart:{ 
          cartItems: cartItemsFromStorage,
          shippingAddress: shippingAddressFromStorage,
        },
    userLogin:{userInfo: userInfoFromStorage},
}

const middleware = [thunk]

const store= createStore(reducer,intitialState, 
                         composeWithDevTools(applyMiddleware(...middleware)))

export default store

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    当您尝试从本地存储中获取 shippingAddress 时,store.js 文件出现拼写错误。你写了sgippingAddress,但应该是shippingAddressh

    【讨论】:

    • 谢谢。我错过了。现在它运行良好!
    • 很高兴听到这个 =)
    【解决方案2】:

    您的 store.js 中有错字;)

    const shippingAddressFromStorage = localStorage.getItem('shippingAddress') ? 
        JSON.parse(localStorage.getItem('->sg<-ippingAddress')) : {}
    

    您可以考虑使用redux-persist,这是一个很好的库,可以将您的 redux 状态持久化到 localStorage、indexDB 等。

    【讨论】:

    • 基本上在同一时间。多么好的时机... =)
    • 谢谢。我错过了。现在它运行良好!也感谢您的建议!
    猜你喜欢
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 2021-10-31
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多