useReducer vs useState
Source: Dev.to
useState
const [contactName, setContactName] = useState("");
const [contactImage, setContactImage] = useState(null);
const [contactImageUrl, setContactImageUrl] = useState(null);
function handleImageUpload(e) {
const file = e.target.files[0];
const fileName = e.targe.files[0].name;
if (!file) return;
const matchRgx = fileName.match(/\.(jpg|png|jpeg)/);
if (matchRgx != null) {
setContactImageUrl(URL.createObjectURL(e.target.files[0]));
} else {
setContactImage(null);
setContactImageUrl(null);
}
}
function handleForm(e) {
e.preventDefault();
window.alert("Successfully added a contact!");
}
return (
Name:
setContactName(e.target.value)}
/>
Image:
Submit
);
useReducer
const initialFormState = { contactName: "", contactImage: null, contactImageUrl: null };
function reducer(state, action) {
if (action.type === "setState") {
return {
...state,
[action.field]: action.value,
};
} else if (action.type === "ImageUpload") {
return {
...state,
contactImage: action.file,
contactImageUrl: action.url,
};
}
return state;
}
const ReducerHook = () => {
const [state, dispatch] = useReducer(reducer, initialFormState);
function handleImageUpload(e) {
const file = e.target.files[0];
const fileName = e.targe.files[0].name;
if (!file) return;
const matchRgx = fileName.match(/\.(jpg|png|jpeg)/);
if (matchRgx != null) {
const imageUrl = URL.createObjectURL(e.target.files[0]);
dispatch({
type: "ImageUpload",
file: e.target.files[0],
url: imageUrl,
});
} else {
dispatch({
type: "ImageUpload",
file: null,
url: null,
});
}
}
function handleName(e) {
e.preventDefault();
}
return (
Name:
{
dispatch({
type: "setState",
field: e.target.name,
value: e.target.value,
});
}}
/>
Image:
Submit
);
};
export default ReducerHook;
Explanation
When using the useState hook, you define a separate setter function (e.g., setContactName) for each piece of state you want to manage.
With useReducer, a single dispatch function is shared among all state updates. The dispatch sends an action to the reducer function, which determines how to update the state based on the action type.
const [state, dispatch] = useReducer(reducer, initialState);
- state – an object containing all tracked values.
- dispatch – a function that sends actions to the reducer.
- reducer – a pure function that receives the current state and an action, returning the new state.
- initialState – the initial values for the state object.