【发布时间】:2021-02-06 21:45:13
【问题描述】:
基本上,我通过将其与 stripe 和 Commercejs 链接来创建一个电子商务测试站点。一切正常,直到结帐表格加载。我可以输入信息,但是,在加载页面时出现错误:
“未处理的拒绝(TypeError):无法读取未定义的属性'id'”仅一行代码。即:
setShippingOption(options[0].id);
该代码嵌套在:
const fetchShippingOptions = async (checkoutTokenId, country, stateProvince = null) => {
const options = await commerce.checkout.getShippingOptions(checkoutTokenId, { country, region: stateProvince });
setShippingOptions(options);
setShippingOption(options[0].id);
};
这段代码本质上是地址形式,如下:
import React, { useState, useEffect } from 'react';
import { InputLabel, Select, MenuItem, Button, Grid, Typography } from '@material-ui/core';
import { useForm, FormProvider } from 'react-hook-form';
import { Link } from 'react-router-dom';
import { commerce } from '../../lib/commerce';
import FormInput from './FormInput';
const AddressForm = ({ checkoutToken, next }) => {
const [shippingCountries, setShippingCountries] = useState([]);
const [shippingCountry, setShippingCountry] = useState('');
const [shippingSubdivisions, setShippingSubdivisions] = useState([]);
const [shippingSubdivision, setShippingSubdivision] = useState('');
const [shippingOptions, setShippingOptions] = useState([]);
const [shippingOption, setShippingOption] = useState('');
const methods = useForm();
const fetchShippingCountries = async (checkoutTokenId) => {
const { countries } = await commerce.services.localeListShippingCountries(checkoutTokenId);
setShippingCountries(countries);
setShippingCountry(Object.keys(countries)[0]);
};
const fetchSubdivisions = async (countryCode) => {
const { subdivisions } = await commerce.services.localeListSubdivisions(countryCode);
setShippingSubdivisions(subdivisions);
setShippingSubdivision(Object.keys(subdivisions)[0]);
};
const fetchShippingOptions = async (checkoutTokenId, country, stateProvince = null) => {
const options = await commerce.checkout.getShippingOptions(checkoutTokenId, { country, region: stateProvince });
setShippingOptions(options);
setShippingOption(options[0].id);
};
useEffect(() => {
fetchShippingCountries(checkoutToken.id);
}, []);
useEffect(() => {
if (shippingCountry) fetchSubdivisions(shippingCountry);
}, [shippingCountry]);
useEffect(() => {
if (shippingSubdivision) fetchShippingOptions(checkoutToken.id, shippingCountry, shippingSubdivision);
}, [shippingSubdivision]);
return (
<>
<Typography variant="h6" gutterBottom>Shipping address</Typography>
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit((data) => next({ ...data, shippingCountry, shippingSubdivision, shippingOption }))}>
<Grid container spacing={3}>
<FormInput required name="firstName" label="First name" />
<FormInput required name="lastName" label="Last name" />
<FormInput required name="address1" label="Address line 1" />
<FormInput required name="email" label="Email" />
<FormInput required name="city" label="City" />
<FormInput required name="zip" label="Zip / Postal code" />
<Grid item xs={12} sm={6}>
<InputLabel>Shipping Country</InputLabel>
<Select value={shippingCountry} fullWidth onChange={(e) => setShippingCountry(e.target.value)}>
{Object.entries(shippingCountries).map(([code, name]) => ({ id: code, label: name })).map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.label}
</MenuItem>
))}
</Select>
</Grid>
<Grid item xs={12} sm={6}>
<InputLabel>Shipping Subdivision</InputLabel>
<Select value={shippingSubdivision} fullWidth onChange={(e) => setShippingSubdivision(e.target.value)}>
{Object.entries(shippingSubdivisions).map(([code, name]) => ({ id: code, label: name })).map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.label}
</MenuItem>
))}
</Select>
</Grid>
<Grid item xs={12} sm={6}>
<InputLabel>Shipping Options</InputLabel>
<Select value={shippingOption} fullWidth onChange={(e) => setShippingOption(e.target.value)}>
{shippingOptions.map((sO) => ({ id: sO.id, label: `${sO.description} - (${sO.price.formatted_with_symbol})` })).map((item) => (
<MenuItem key={item.id} value={item.id}>
{item.label}
</MenuItem>
))}
</Select>
</Grid>
</Grid>
<br />
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Button component={Link} variant="outlined" to="/cart">Back to Cart</Button>
<Button type="submit" variant="contained" color="primary">Next</Button>
</div>
</form>
</FormProvider>
</>
);
};
export default AddressForm;
除此之外,这是我收到的唯一错误。
顺便说一句,我对 JavaScript 还是很陌生,我刚上大学一年级。
【问题讨论】:
-
您确定这些选项有 id 属性吗?
-
将
console.log(options)放在setShippingOptions(options);之前,看看它为控制台打印了什么。 -
这样你就有了。
await commerce.checkout.getShippingOptions返回一个空数组,而我假设它应该返回一个对象数组。 -
options[0]未定义,因此没有可访问的id属性。您应该首先检查数组长度,或者使用可选链接运算符,即options[0]?.id。 -
我的意思是你可以先检查
options[0]是否存在,然后再访问该对象,例如options[0] && options[0].id。 Optional Chaining 运算符允许您更简洁地编写此代码。没有像官方文档这样的东西??? :developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
标签: javascript reactjs e-commerce