无法从对象中获取 ID
2021-07-19
120
我尝试使用 console.log(checkoutToken.id)。但是我无法访问此属性,我不明白为什么。我可以将 checkoutToken 打印到控制台,但无法访问 id 属性?
fetchShippingCountries(checkoutToken.id) 也给我带来了同样的问题。我是否没有正确传递 props?
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 "../CheckoutForm/CustomTxtField";
const AddressForm = ({ checkoutToken, test }) => {
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
);
console.log(countries);
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);
};
console.log(checkoutToken);
useEffect(() => {
fetchShippingCountries(checkoutToken);
}, []);
useEffect(() => {
fetchShippingCountries(checkoutToken.id);
}, []);
useEffect(() => {
if (shippingCountry) fetchSubdivisions(shippingCountry);
}, [shippingCountry]);
useEffect(() => {
if (shippingSubdivision)
fetchShippingOptions(
checkoutToken.id,
shippingCountry,
shippingSubdivision
);
}, [shippingSubdivision]);
return (
<div>
<Typography variant="h6" gutterBottom>
Shipping address
</Typography>
<FormProvider {...methods}>
<form
onSubmit={methods.handleSubmit((data) =>
test({
...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>
</div>
);
};
export default AddressForm;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import React, { useState, useEffect } from "react";
import {
Paper,
Stepper,
Step,
StepLabel,
Typography,
CircularProgress,
Divider,
Button,
} from "@material-ui/core";
import { Link, useHistory } from "react-router-dom";
import useStyles from "./styles";
import AddressForm from "../AddressForm";
import PaymentForm from "../PaymentForm";
import { commerce } from "../../../lib/Commerce";
const steps = ["Shipping address", "Payment details"];
const Checkout = ({ cart }) => {
const [activeStep, setActiveStep] = useState(0);
const classes = useStyles();
const [checkoutToken, setCheckoutToken] = useState(null);
const [shippingData, setShippingData] = useState({});
const history = useHistory();
const nextStep = () => setActiveStep((prevActiveStep) => prevActiveStep + 1);
const backStep = () => setActiveStep((prevActiveStep) => prevActiveStep + 1);
useEffect(() => {
if (cart.id) {
const generateToken = async () => {
try {
const token = await commerce.checkout.generateToken(cart.id, {
type: "cart",
});
console.log(token);
setCheckoutToken(token);
console.log(checkoutToken);
} catch (error) {
if (activeStep !== steps.length) history.push("/");
}
};
generateToken();
console.log(checkoutToken.id);
}
}, []);
const test = (data) => {
setShippingData(data);
nextStep();
};
const Conformation = () => <div>Conformation</div>;
const Form = () =>
activeStep === 0 ? (
<AddressForm checkoutToken={checkoutToken} test={test} />
) : (
<PaymentForm />
);
return (
<div className={classes.toolbar}>
<main className={classes.layout}>
<Paper className={classes.paper}>
<Typography varient="h4" alignment="center"></Typography>
<Stepper activeStep={activeStep} className={classes.stepper}>
{steps.map((step) => (
<Step key={step}>
<StepLabel>{step}</StepLabel>
</Step>
))}
</Stepper>
{activeStep === steps.length ? <Conformation /> : <Form />}
</Paper>
</main>
</div>
);
};
export default Checkout;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
1个回答
您可能无法获得它的原因是 useEffect 没有任何依赖项,仅运行一次,如果您将 checkoutToken 作为依赖项传递,那么它将在每次 checkoutToken props 更改时运行,您第一次无法访问它的原因是因为它在第一种情况下可能未定义
因此请像下面这样替换 useEffect
useEffect(() => {
if(checkoutToken && checkoutToken.id){
fetchShippingCountries(checkoutToken);
}
}, [checkoutToken]);
Goutham J.M
2021-07-19