There is a state initialized with an array of objects:
interface Product {
id: number;
status: boolean;
color: string;
price: number;
}
const productList: Product[] = [
{
id: 1,
status: true,
color: 'yellow',
price: 275
},
{
id: 2,
status: true,
color: 'blue',
price: 325
}
];
const [products, setProducts] = useState<Product[]>(productList);
Only those products are displayed for which the property status == true.
I’m trying to delete a product, so I calculate the new state using the previous state:
const productsRender = products.map((product: Product): false | JSX.Element => {
return(product.status &&
<ProductWrapper>
<Product key={product.id}>
<Remove
type='button'
onClick={(): void =>
//TypeScript error TS2345
setProducts(prevProducts => [...prevProducts, product.status = false])
}
/>
<Color>color: {product.color}</Color>
<Price>${product.price}</Price>
</Product>
</ProductWrapper>
);
});
But I am getting an error:
Argument of type '(prevProducts: Product[]) => (boolean | Product)[]' is not assignable to parameter of type 'SetStateAction<Product[]>'.
Type '(prevProducts: Product[]) => (boolean | Product)[]' is not assignable to type '(prevState: Product[]) => Product[]'.
Type '(boolean | Product)[]' is not assignable to type 'Product[]'.
Type 'boolean | Product' is not assignable to type 'Product'.
Type 'boolean' is not assignable to type 'Product'.
I have tried not passing the function in setProducts:
setProducts([...products, product.status = false])
But I get TypeScript error TS2322:
Type 'boolean | Product' is not assignable to type 'Product'.
Type 'boolean' is not assignable to type 'Product'.
It’s not clear to me how to properly update the state.
I would be grateful for help.
>Solution :
When using ...products, you’re referring to the previous products in the array and you’re trying to append a product.status = false to the array, which is not a Product.
If you want to update the last value of the products array, you can do this.
const productsRender = products.map((product: Product): false | JSX.Element => {
return(product.status &&
<ProductWrapper>
<Product key={product.id}>
<Remove
type='button'
onClick={(): void => {
let new_products = [...products];
let atIndex = products.indexOf(product);
new_products[atIndex].status = false;
setProducts(new_products);
// This might work - haven't tested
//let atIndex = products.indexOf(product);
//products[atIndex].status = false;
//setProducts(products);
}}
/>
<Color>color: {product.color}</Color>
<Price>${product.price}</Price>
</Product>
</ProductWrapper>
);
});
There might be another way (much prettier).