Reputation: 72
I cant figure out why when I add an item to my store the app resets. I can see for a split second that its being added to my list but then I can see all my component flicker and reload. Inspecting the console doesn't bring up any warnings.
I also plugged in just my addProduct component and productsSlice into the redux template and it also reloaded the app.
Basic HTML for adding a product with hooks:
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { addProduct } from '../_reducers/productsSlice'
const AddProduct = () => {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('')
const [price, setPrice] = useState('')
const onTitleChanged = e => setTitle(e.target.value);
const onDescriptionChanged = e => setDescription(e.target.value);
const onPriceChanged = e => setPrice(e.target.value);
const dispatch = useDispatch();
return (
<section>
<h2>Add a new Product</h2>
<form>
<label htmlFor="Title">Title</label>
<input
type="text"
name="title"
value={title}
onChange={onTitleChanged} />
<label htmlFor="Price">Price</label>
<input
type="text"
value={price}
onChange={onPriceChanged} />
<label htmlFor="Description">Description</label>
<textarea
value={description}
onChange={onDescriptionChanged} />
<button onClick={() => dispatch(addProduct({
title: title,
price: price,
description: description
}))}>
Submit
</button>
</form>
</section>
)
}
export default AddProduct;
My Reducer:
import { createSlice } from '@reduxjs/toolkit'
const initialProductsState = [
// { name: '1', price: 10, description: 'testDescrip1' },
// { name: '2', price: 20, description: 'testDescrip2' },
// { name: '3', price: 30, description: 'testDescrip3' },
{ name: '4', price: 40, description: 'testDescrip4' }]
export const productsSlice = createSlice({
name: 'products',
initialState: initialProductsState,
reducers: {
addProduct: (state, action) => {
state.push(action.payload)
},
}
})
export const { addProduct } = productsSlice.actions;
export default productsSlice.reducer
Listing of the products:
import React from 'react';
import { useSelector } from 'react-redux'
import { Row, Col } from 'react-bootstrap'
import ProductItem from "./ProductItem"
const ProductList = () => {
const products = useSelector(state => state.products)
let numberRendered = 3;
const renderedProducts = products.map(item => (
<ProductItem product={item} />
))
return (
<div id="ProductList">
<Row>
<Col>
{renderedProducts}
</Col>
</Row>
</div>
)
}
export default ProductList;
And the product component styled with react-bootstrap:
import React from 'react';
import {productSlice} from '../_reducers/productsSlice';
import { Card, Col, Row } from 'react-bootstrap'
const ProductItem = (props) => {
return (
<Card>
<Card.Body>
<Row>
<Col md={4}>
<Card.Img variant="float" src={process.env.PUBLIC_URL + 'placeholder.png'} />
</Col>
<Col md={8}>
<Card.Title>{props.product.title}</Card.Title>
<Card.Text>{props.product.description}</Card.Text>
<Card.Subtitle>{props.product.price}</Card.Subtitle>
</Col>
</Row>
</Card.Body>
</Card>
)
}
export default ProductItem;
store:
import { configureStore } from '@reduxjs/toolkit'
import productsSlice from '../src/_reducers/productsSlice'
const store = configureStore({
reducer: {
products: productsSlice,
}
})
export default store;
Upvotes: 0
Views: 47
Reputation: 621
Pretty sure you just need to add an event.preventDefault()
to the form's submit event
import React, { useState } from 'react'
import { useDispatch } from 'react-redux'
import { addProduct } from '../_reducers/productsSlice'
const AddProduct = () => {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('')
const [price, setPrice] = useState('')
const onTitleChanged = e => setTitle(e.target.value);
const onDescriptionChanged = e => setDescription(e.target.value);
const onPriceChanged = e => setPrice(e.target.value);
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
dispatch(addProduct({
title: title,
price: price,
description: description
}))
}
return (
<section>
<h2>Add a new Product</h2>
<form onSubmit={handleSubmit}>
<label htmlFor="Title">Title</label>
<input
type="text"
name="title"
value={title}
onChange={onTitleChanged} />
<label htmlFor="Price">Price</label>
<input
type="text"
value={price}
onChange={onPriceChanged} />
<label htmlFor="Description">Description</label>
<textarea
value={description}
onChange={onDescriptionChanged} />
<button type="submit">
Submit
</button>
</form>
</section>
)
}
export default AddProduct;
Without the preventDefault
submitting the form will submit a get request to the same route, which will cause the component to reload.
Upvotes: 1