features/productSlice.js
export const resetState = createAction("Reset_all")
const initialState = {
products: [],
product: {},
productImages: [],
isError: false,
isLoading: false,
isLoadingPhoto: false,
isSuccess: false,
message: "",
}
export const productSlice = createSlice({
name: "product",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(getProducts.pending, (state) => {
state.isLoading = true;
})
.addCase(getProducts.fulfilled, (state, action) => {
state.isLoading = false;
state.isError = false;
state.isSuccess = true;
state.products = action.payload;
})
.addCase(getProducts.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.isSuccess = false;
state.message = action.error;
})
.addCase(getAProduct.pending, (state) => {
state.isLoading = true;
})
.addCase(getAProduct.fulfilled, (state, action) => {
state.isLoading = false;
state.isError = false;
state.isSuccess = true;
state.product['name'] = action.payload.title
state.product['description'] = action.payload.description
state.product['price'] = action.payload.price
state.product['brand'] = action.payload.brand
state.product['category'] = action.payload.category
state.product['tags'] = action.payload.tags
state.product['colors'] = action.payload.color
state.product['quantity'] = action.payload.quantity
// state.product['images'] = action.payload.images
state.productImages = action.payload.images
})
.addCase(getAProduct.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.isSuccess = false;
state.message = action.error;
})
.addCase(resetState, () => initialState)
}
})
export default productSlice.reducer
pages/ProductList.jsx
useEffect(() => {
dispatch(getProducts())
}, [])
const productState = useSelector((state) => state.product?.products)
const data1 = [];
for (let i = 0; i < productState.length; i++) {
data1.push({
key: i + 1,
title: productState[i].title,
image: (
<img style={{objectFit: "cover"}} src={productState[i].images[0].url} width={50} height={50} />
),
brand: productState[i].brand,
category: productState[i].category,
color: productState[i].color,
quantity: productState[i].quantity,
price: `${productState[i].price}`,
action: (
<div className='d-flex align-items-center'>
<Link
to={`/admin/product/${productState[i]._id}`}
className=" fs-3 text-success"
> <-- Link redirecting to update product with formik
<BiEdit />
</Link>
<button
className="ms-3 fs-3 text-danger bg-transparent border-0"
// onClick={() => showModal(productState[i]._id)}
>
<AiFillDelete />
</button>
</div>
)
});
}
pages/AddProductForm.jsx
const newProduct = useSelector((state) => state.product)
const { isSuccess, isError, isLoading, isLoadingPhoto, createdProduct, product, productImages } = newProduct
const formik = useFormik({
initialValues: {
title: product.name || "",
description: product.description || "",
price: product.price || "",
brand: product.brand || "",
category: product.category || "",
quantity: product.quantity || "",
color: selectedColors ? selectedColors : [],
images: productImages ? productImages : []
},
validationSchema: schema,
onSubmit: (values) => {
console.log(values)
}
})
useEffect(() => {
if(id !== undefined){
formik.resetForm()
dispatch(resetState()) <-- I tried to reset to initial state and reset the formik form before reading the corresponding data
dispatch(getAProduct(id))
} else{
dispatch(resetState())
}
}, [id])
return (
<div className="col-10">
<CustomInput
type="text"
label="Enter product title"
name="title"
onChange={formik.handleChange("title")}
onBlur={formik.handleBlur("title")}
val={formik.values.title}
/>
</div>
I have an issue that I would like to read the existing data when accessing the page for AddProduct
dispatching getAProduct(id)
but if I clicked the windows back button or change another route the data could not be reset. Also, the data could not be read correctly while clicking another data from the table in ProductList
that it still displaying the previous values in formik until I refresh the page. Are there any solutions to fix this bug?
I have been trying to reset the redux state in different ways but no one works even if I console.log
the values they are showing correctly but not displaying correctly in formik
Try with the clean-up function. Like
useEffect(() => {
if(id !== undefined){
dispatch(getAProduct(id))
}
return()=>{
formik.resetForm()
dispatch(resetState()) <-- I tried to reset to initial state and reset the formik form before reading the corresponding data
}
}, [id])
This will clear the form and state when you change the route or close the form component