// formReducer.tsx
interface FormState {
title: string;
desc: string;
price: number;
category: string;
tags: string[];
images: {
sm: string;
md: string;
lg: string;
};
quantity: number;
}
interface FormAction {
type: string;
payload?: any;
}
export const INITIAL_STATE: FormState = {
title: "",
desc: "",
price: 0,
category: "",
tags: [],
images: {
sm: "",
md: "",
lg: "",
},
quantity: 0,
};
export const formReducer = (state: FormState, action: FormAction): FormState => {
switch (action.type) {
case "CHANGE_INPUT":
return {
...state,
[action.payload.name]: action.payload.value,
};
case "ADD_TAG":
return {
...state,
tags: [...state.tags, action.payload],
};
case "REMOVE_TAG":
return {
...state,
tags: state.tags.filter((tag) => tag !== action.payload),
};
case "INCREASE":
return {
...state,
quantity: state.quantity + 1,
};
case "DECREASE":
return { ...state, quantity: state.quantity - 1 };
default:
return state;
}
};
// Form.tsx
import React, { useReducer, useRef, useState } from "react";
import { formReducer, INITIAL_STATE } from "./formReducer";
const Form = () => {
const [state, dispatch] = useReducer(formReducer, INITIAL_STATE);
const tagRef = useRef<HTMLTextAreaElement>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
dispatch({
type: "CHANGE_INPUT",
payload: { name: e.target.name, value: e.target.value },
});
};
const handleTags = () => {
const tags = tagRef.current?.value.split(",");
if (tags) {
tags.forEach((tag) => {
dispatch({ type: "ADD_TAG", payload: tag });
});
}
};
return (
<div>
<form>
<input
type="text"
placeholder="Title"
onChange={handleChange}
name="title"
value={state.title}
/>
<input
type="text"
placeholder="Desc"
onChange={handleChange}
name="desc"
value={state.desc}
/>
<input
type="number"
placeholder="Price"
onChange={handleChange}
name="price"
value={state.price}
/>
<p>Category:</p>
<select onChange={handleChange} name="category" value={state.category}>
<option value="sneakers">Sneakers</option>
<option value="tshirts">T-shirts</option>
<option value="jeans">Jeans</option>
</select>
<p>Tags:</p>
<textarea ref={tagRef} placeholder="Seperate tags with commas..."></textarea>
<button onClick={handleTags} type="button">
Add Tags
</button>
<div className="tags">
{state.tags.map((tag) => (
<small
onClick={() => dispatch({ type: "REMOVE_TAG", payload: tag })}
key={tag}
>
{tag}
</small>
))}
</div>
<div className="quantity">
<button onClick={() => dispatch({ type: "DECREASE" })} type="button">
-
</button>
<span>Quantity ({state.quantity})</span>
<button onClick={() => dispatch({ type: "INCREASE" })} type="button">
+
</button>
</div>
</form>
</div>
);
};