'Commerce JS, generateToken returning "Material-UI: A component is changing the controlled value state of Select to be uncontrolled."

This is where i generate the token

import React, { useState, useEffect } from 'react';
import { Paper, Stepper, Step, StepLabel, Typography, CircularProgress, Divider, Button } from '@material-ui/core';

import { commerce } from '../../../lib/commerce';
import useStyles from './styles';
import AddressForm from '../AddressForm';
import PaymentForm from '../PaymentForm';

const steps = ['Shipping address', 'Payment details'];

const Checkout = ({ cart }) => {
    const [activeStep, setActiveStep] = useState(0);
    const [checkoutToken, setCheckoutToken] = useState(null);
    const classes = useStyles();

useEffect(() => {
    if (cart.id) {
        const generateToken = async () => {
            try {
                const token = await commerce.checkout.generateToken(cart.id, { type: 'cart' });

                setCheckoutToken(token)
            } catch (error){
                console.log(error);
            }
        };

        generateToken();
    }

}, [cart]);

const Confirmation = () => (
    <div>
        Confirmation
    </div>
)

const Form = () => activeStep === 0
    ? <AddressForm checkoutToken={checkoutToken} />
    : <PaymentForm />

return (
    <>
        <div className={classes.toolbar} />
        <main className={classes.layout} >
            <Paper className={classes.paper}>
                <Typography variant='h4' align='center'>Checkout</Typography>
                <Stepper activeStep={activeStep} className={classes.stepper}>
                    {steps.map((step) => (
                        <Step key={step}>
                            <StepLabel>{step}</StepLabel>
                        </Step>
                    ))}
                </Stepper>
                {activeStep === steps.length ? <Confirmation /> : checkoutToken && <Form />}
            </Paper>
        </main>
    </>
)
}

 export default Checkout

Here is my App.js

import React, { useState, useEffect, Fragment } from 'react'
import { commerce } from './lib/commerce';
import { Products, Navbar, Cart, Checkout } from './components';
import { BrowserRouter as Router, Routes, Route} from 'react-router-dom';

const App = () => {
    const [products, setProducts] = useState([]);
    const [cart, setCart] = useState({});

const fetchProducts = async () => {
    const { data } = await commerce.products.list();

    setProducts(data);
}

const fetchCart = async () => {
    setCart(await commerce.cart.retrieve())
}

const handleAddToCart = async ( productId, quantity) =>{
    const { cart } = await commerce.cart.add(productId, quantity);
    
    setCart(cart);
}

const handleUpdateCartQty = async (productId, quantity) => {
    const { cart } = await commerce.cart.update(productId, { quantity });

    setCart(cart);
}

const handleRemoveFromCart = async (productId) => {
    const { cart } = await commerce.cart.remove(productId);

    setCart(cart);
}

const handleEmptyCart = async () => {
    const { cart } = await commerce.cart.empty();

    setCart(cart);
}

useEffect(() => {
    fetchProducts();
    fetchCart();
}, []);

return (
    <Router>
        <div>
            <Navbar totalItems={cart.total_items} />
            <Routes>
                <Route exact path='/' element={<Products products={products} onAddToCart={handleAddToCart} />} />
                <Route exact path='/cart' element={<Cart cart={cart} handleUpdateCartQty={handleUpdateCartQty} handleAddToCart={handleAddToCart} handleRemoveFromCart={handleRemoveFromCart} handleEmptyCart={handleEmptyCart} />} />
                <Route exact path='/checkout' element={ <Checkout cart={cart} />} />
            </Routes>
        </div>
    </Router>
)
}


export default App;

And here is my cart.jsx incase their is anything relevant there

import React from 'react'
import { Container, Typography, Button, Grid} from '@material-ui/core';
import { Link } from 'react-router-dom';

import useStyles from './styles';
import CartItem from './CartItem/CartItem';

const Cart = ({ cart, handleUpdateCartQty, handleRemoveFromCart, handleEmptyCart }) => {
    const classes = useStyles();

    const EmptyCart = () => (
        <Typography variant='subtitle1'>
            You have no items in your shopping cart.
            <Link to='/' className={classes.link}>Add Items!</Link>
        </Typography>
);

const FilledCart = () => (
    <>
        <Grid container spacing={3}>
            { cart.line_items.map((item) => (
                <Grid item xs={12} sm={4} key={item.id}>
                    <CartItem item={item} onUpdateCartQty={handleUpdateCartQty} onRemoveFromCart={handleRemoveFromCart} />
                </Grid>
            ))}
        </Grid>
        <div className={classes.cardDetails}>
                <Typography variant='h4'>
                    Subtotal: {cart.subtotal.formatted_with_symbol}
                    <div>
                        <Button className={classes.emptyButton} size='large' type='button' variant='contained' color='secondary' onClick={handleEmptyCart}>
                            Empty Cart
                        </Button>
                        <Button component={Link} to='/checkout' className={classes.checkoutButton} size='large' type='button' variant='contained' color='primary'>
                            Checkout
                        </Button>
                    </div>
                </Typography>
        </div>
    </>
);

// Wait for cart to load items
if(!cart.line_items){
    return '...loading';
}

return (
<Container>
    <div className={classes.toolbar} />
    <Typography className={classes.title} varaint='h3' gutterBottom >Your Shopping Cart</Typography>
    { !cart.line_items.length ? <EmptyCart /> : <FilledCart />}
</Container>
)
}
export default Cart

[error messages][1] [1]: https://i.stack.imgur.com/vlard.png

Warning: Expected onSubmit listener to be a function, instead got a value of string type. form FormProvider@http://localhost:3000/static/js/bundle.js:76722:7 AddressForm@http://localhost:3000/static/js/bundle.js:1096:7 Form div Paper@http://localhost:3000/static/js/bundle.js:12332:17 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 main Checkout@http://localhost:3000/static/js/bundle.js:1332:7 Routes@http://localhost:3000/static/js/bundle.js:67209:7 div Router@http://localhost:3000/static/js/bundle.js:67146:7 BrowserRouter@http://localhost:3000/static/js/bundle.js:65952:7 App@http://localhost:3000/static/js/bundle.js:347:82

Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components input SelectInput@http://localhost:3000/static/js/bundle.js:13482:19 div InputBase@http://localhost:3000/static/js/bundle.js:8257:25 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 Input@http://localhost:3000/static/js/bundle.js:9146:26 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 Select@http://localhost:3000/static/js/bundle.js:13182:26 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 div Grid@http://localhost:3000/static/js/bundle.js:7352:29 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 div Grid@http://localhost:3000/static/js/bundle.js:7352:29 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 form FormProvider@http://localhost:3000/static/js/bundle.js:76722:7 AddressForm@http://localhost:3000/static/js/bundle.js:1096:7 Form div Paper@http://localhost:3000/static/js/bundle.js:12332:17 WithStyles@http://localhost:3000/static/js/bundle.js:19639:25 main Checkout@http://localhost:3000/static/js/bundle.js:1332:7 Routes@http://localhost:3000/static/js/bundle.js:67209:7



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source