Ошибка типа: не удается прочитать свойство ‘length’ неопределенного значения в react js

#reactjs #react-redux

#reactjs #react-redux

Вопрос:

Предполагается, что мой код генерирует всплывающее окно продукта, а затем добавляет продукт на страницу списка пожеланий. Это выдает ошибку, что длина не определена, я думаю, это потому, что я неправильно использовал хуки, я попытался добавить const [listVariations, setListVariations] = useState(0) вместо const [listVariations, setListVariations] = useState([]), но он по-прежнему выдает ту же ошибку может кто-нибудь помочь мне разобратьсязаранее спасибо!

 import React, { Fragment, useContext, useState, useEffect} from 'react'
import './Sass/Index.scss'
import { WishListContext } from '../../contexts/WishListContext'
import { ProductContext } from '../../contexts/ProductContext'
import Popup from "reactjs-popup";

const Product = ({product, id, productIndex}) => {
    const{name, price, image, variation, option, unit, total} = product
    const {wishListState, wishListDispatch} = useContext(WishListContext)
    const {productState} = useContext(ProductContext)
    const [popupVariation, setPopupVariation] = useState(false)
    const [popupOption, setPopupOption] = useState(false)
    const [listVariations, setListVariations] = useState([])
    const [listOptions, setListOptions] = useState([])
    const [selectedOption, setSelectedOption] = useState({})
    const [updateToggle, setUpdateToggle] = useState(false)
   

    useEffect(()=> {
        generatePopupVariation()
        generatePopupOptions()
    }, [productState])

    const updateLocalStorage = (products) => {
        if (products.length > 0) {
            wishListDispatch({
                type:"REPLACE_WISH",
                payload: products.map(item => item)
            })
        } 
    }

    const generatePopupOptions = () => {
        const products = productState.products
        if (products.length > 0) {
            const finedProduct = products.find(item => item.id === id)
            const priceOptions = finedProduct?.data.priceOptions
            setListOptions(priceOptions amp;amp; priceOptions[0].options) 
        }
    }

    const generatePopupOptionContent= () => {
        if ( listOptions.length > 0 ) {
           const filtered = listOptions.filter(item => item.is_available !== 'No')
           return filtered.map((item, index) => <li key={index}><span>{item.option}</span><span>Price: {item.price}</span><div className="btn btn-primary" onClick={() => changeOption(index, item.option, item.price)} >Select</div></li>)
        }
    }

    const changeOption = (index, option, price) => {
        const action = {
            id,
            option,
            price
        }
        if (option) {
            wishListDispatch({
                type:'UPDATE_OPTION_WISH',
                action
            })
            updateLocalStorage(wishListState.products)
            modalOption('close')
        }  
    }

  
    const generatePopupVariation = () => {
        const products = productState.products
        if (products.length > 0) {
            const finedProduct = products.find(item => item.id === id)
            const priceOptions = finedProduct?.data.priceOptions
            setListVariations(priceOptions)
        }
    }

    const generatePopupVariationContent = () => {
     
     if ( listVariations.length > 0 ) {
      console.log(listVariations.length)
      return listVariations.map((item, index) => <li className="btn btn-primary" onClick={() => changeVariation(index, item.variation, item.options)} key={index}>{item.variation}</li>)
   }
    }

    const changeVariation = (index, variation, options) => {
        const action = {
            id,
            variation
        }
        if (variation) {
            wishListDispatch({
                type:'UPDATE_VARIATION_WISH',
                action
            })
            updateLocalStorage(wishListState.products)
            modalVariation('close')
        }  
    }
    
    const handleRemove = () => {
        if (wishListState) {
            if( wishListState.products.length > 0) {
                wishListDispatch({
                    type: 'REMOVE_WISH',
                    payload: productIndex
                })
            }
        }
    }
    const handleUnit = (control) => {
        if (wishListState) {
            if( wishListState.products.length > 0) {
                wishListDispatch({
                    type: 'ADD_UNIT_WISH',
                    payload: {index: productIndex, control:control}
                })
            }
        }
    }
    const modalVariation = action => {
        if (action === 'open') {
            setPopupVariation(true)
        } else if (action === 'close') {
            setPopupVariation(false)
        }
    }
    const modalOption = action => {
        if (action === 'open') {
            setPopupOption(true)
        } else if (action === 'close') {
            setPopupOption(false)
        }
    }

    return (
        <Fragment>
            <Popup
                open={popupVariation}
                closeOnDocumentClick
                onClose={()=> modalVariation('close')}
            >
                <div className="popup-content"> 
                    <ul>
                        {generatePopupVariationContent()}
                    </ul>
                    <span onClick={() => modalVariation('close')}>X</span>
                </div>
            </Popup>
            <Popup
                open={popupOption}
                closeOnDocumentClick
                onClose={()=> modalOption('close')}
            >
                <div className="popup-content"> 
                    <ul>
                        {generatePopupOptionContent()}
                    </ul>
                    <span onClick={() => modalOption('close')}>X</span>
                </div>
            </Popup>
                <div className="card">
                    <div className="card-wrapper">
                        <div className="left">
                            <img className="card-img" src={ image } alt={ name } />
                        </div>
                        <div className="right">
                            <div className="card-remove" onClick={handleRemove}>
                                <i className="times" name="close"></i>
                            </div>
                            <h4 className="card-title">{ name }</h4>
                            { variation amp;amp; <p className="card-variation"><span>Variation:</span><span>{variation} <span onClick={()=> modalVariation('open')} className="change-variation"><ion-icon name="create"></ion-icon></span></span> </p>}
                            { option amp;amp; <p className="card-option"><span>Option:</span><span> { option }  <span onClick={()=> modalOption('open')} className="change-option"><ion-icon name="create"></ion-icon></span></span></p>}
                            <div className="card-unit"><span>Qty:</span>
                                <div className="card-units-wrapper">
                                    <i className="plus" name="add" onClick={() => handleUnit(' ')}></i>
                                    <div className="card-units">{unit}</div>
                                    <i className="minus" name="remove" onClick={() => handleUnit('-')}></i>
                                </div>
                            </div>
                            <p className="card-price"><span>Price:</span><span> {price} </span></p>
                            <p className="card-total"><span>Total:</span> <span>{total} </span></p>
                        </div>
                    </div>
                </div>
        </Fragment>
    )
}

export default Product
 

ProductContext.js

 import React, { createContext, useReducer } from 'react'
import ProductReducer from '../reducers/ProductReducer'

export const ProductContext = createContext()

const initState = {
    products: []
}

const ProductProvider = props => {
    const [ productState, productDispatch ] = useReducer(ProductReducer, initState)
    const value = {productState, productDispatch}
    return (
        <ProductContext.Provider value={value}>
            {props.children}
        </ProductContext.Provider>
    )
}

export default ProductProvider
 

ProductReducer.js

 const ProductReducer = (state, action) => {
    switch (action.type) {
        case "LOAD_PRODUCTS":
            return {...state, products: [...action.payload]}
        case "ADD_PRODUCT":
            return {...state, products: [...state.products, action.payload]}
        default:
            return state
    }
}
export default ProductReducer;
 

WishlistContext.js

 import React, { createContext, useReducer } from 'react'
import WishListReducer from '../reducers/WishListReducer'
export const WishListContext = createContext()

const initState = {
    products: [],
    select_variation:null
}
const WishListProvider = props => {
    const [ wishListState, wishListDispatch ] = useReducer(WishListReducer, initState)
    const value = {wishListState, wishListDispatch }
    return (
        <WishListContext.Provider value={value}>
            {props.children}
        </WishListContext.Provider>
    )
}

export default WishListProvider
 

WishlistReducer.js

 const WishListReducer = (state, action) => {
    switch (action.type) {
        case "ADD_WISH":
            return addWish(state, action)
        case "REPLACE_WISH":
            return replaceWish(state, action)
        case "REMOVE_WISH":
            return removeWish(state, action)
        case "ADD_UNIT_WISH":
            return unitWish(state, action)
        case "UPDATE_VARIATION_WISH":
            return updateVariation(state, action)
        case "UPDATE_OPTION_WISH":
            return updateOption(state, action)
        default:
            return state
    }
}

const addWish = (state, action) => {
    localStorage.setItem('wish-list', JSON.stringify({...state, products: [...state.products, action.payload] }))
    return {...state, products: [...state.products, action.payload] }
}

const replaceWish = (state, action) => {
    localStorage.setItem('wish-list', JSON.stringify({...state, products: [...action.payload] }))
    return {...state, products: [...action.payload] }
}

const removeWish = (state, action) => {
    const copyState = {...state }
    copyState.products.splice(action.payload, 1);
    localStorage.setItem('wish-list', JSON.stringify({...state, products: [...copyState.products] }))
    return {...state, products: [...copyState.products] }
}

const unitWish = (state, action) => {
    const copyState = {...state }
    const index = copyState.products[action.payload.index]
    const ctrl = action.payload.control
    const unit = index.unit
    const price = index.price
    if (ctrl == " ") {
        index.unit = Number(unit)   1
        index.total = Number(price) * (Number(unit)   1)
    }
    if (ctrl == "-") {
        if (Number(unit) <= 1) {
            index.unit = 1
        } else {
            index.unit = Number(unit) - 1
            index.total = Number(price) * (Number(unit) - 1)
        }
    }
    localStorage.setItem('wish-list', JSON.stringify({...state, products: [...copyState.products] }))
    return {...state, products: [...copyState.products] }
}

const updateVariation = (state, action) => {
    const id = action.action.id
    const variation = action.action.variation
    const copyState = {...state }
    const product = copyState.products.find(item => item.id == id)
    product.variation = variation
    return {...state, products: [...copyState.products] }
}

const updateOption = (state, action) => {
    const id = action.action.id
    const option = action.action.option
    const price = action.action.price
    const copyState = {...state }
    const product = copyState.products.find(item => item.id === id)
    product.option = option
    product.price = price
    product.total = product.unit * price
    return {...state, products: [...copyState.products] }
}


export default WishListReducer;
 

Комментарии:

1. Не могли бы вы указать, какая строка в коде выдает ошибку? У вас есть 8 экземпляров .length , и было бы полезно уточнить.

2. У вас есть два контекста, которые могут вызывать эту проблему, если вы проверяете length их products свойство

3. Покажите нам свою productState.products структуру.

4. @AntonioErdeljac список вариантов. длина> 0 , это

Ответ №1:

В основном, часть содержимого, используемого с.длина не определена. Лучший способ узнать, какой из них есть undefined , — использовать typeof . Вы можете использовать typeof variableName для определения типа переменной. Если некоторые типы в коде не являются списком или массивом, это приведет к ошибке. Для отладки вы можете использовать alert("Type is not valid") методы combined with для просмотра. (Кстати, у нас нет этих данных, и мы определяем, в чем ошибка.)

Комментарии:

1. Я уже делал это, тип переменной является объектом, затем, как я упоминал ранее, я попытался заменить const [listVariations, setListVariations] = useState(0) вместо const [listVariations, setListVariations] = useState([]) как .длина не может быть применена к объектам

2. Не могли бы вы попробовать useState(new Array())