React hook form - onsubmit with data from usestate - reactjs

on handleSubmit i want to send array (fetchExcluded) but object checkboxes from useState i get empty object inside handleSaveOparation function.
please tell me how can I get data inside handlesubmit
const defaultValues = {
sum: '',
};
const {
handleSubmit,
control,
watch,
setValue,
formState: { errors, isValid },
} = useForm<OperationsData>({ defaultValues, resolver: yupResolver(schema), mode: 'onSubmit' });
const [checkboxes, setCheckboxes] = useState({});
const fetchExcluded = useMemo(
() => Object.entries(checkboxes)?.map(([k, v]) => ({ id: k, included: v })),
[checkboxes],
);
console.log('fetchExcluded', fetchExcluded);//[{id:1,included:true}]
console.log('checkboxes', checkboxes);//{1:true}
const handleSaveOperation = useCallback(
handleSubmit((data) => {
const { sum } = data;
console.log('checkboxes', checkboxes);//{}
console.log('fetchExcluded', fetchExcluded);//[]
}),
[checkboxes, date, fetchExcluded, handleSubmit],
);
return (
<form onSubmit={handleSaveOperation}>...formComponents</form>
)

Related

How to Effective set value from bottom to top useState value in react on react hook form in defaultValues?

const { isLoading, data } = useQuery('orderData', () =>
fetch(`http://localhost:5000/data/${id}`).then(res =>
res.json()
)
)
const [value, setValue] = useState(0)
const { register, formState: { errors }, handleSubmit, reset } = useForm({ defaultValues: { quantity: value } });
if (isLoading) {return <LoadingPage />}
const { _id, name, imgURL, description, minQuantity, availableQuantity, price } = data
after doing this code i want to set setValue(minQuantity)
I am trying it different way but i am getting error , nothing see on output and didn't get anymore idea ..

Somebody knows how to populate this field showing in the picture below with specific data object?

this is the image(click here!) where you can see our web page with certain fields, that one of the field with arrow is the one didn't populate object from the backend
this is written with react & typescript & our backend is java springboot & MySQL as database.
and here is the code that i'm suspected , having a issue:
const AddUsers: FC = (props) => {
const navigate = useNavigate();
// const { id } = useParams();
const dispatch = useDispatch();
const roleList = useGetRoleList()
const user = useCurrentUser();
const [rolesInput, setRolesInput] = useState<MultiValue<{ value: string; label: string; }>>([]);
const isFetching = useInviteUserLoading()
const permitted = useCheckPermission(ROLES.ADD_USER)
const { register, handleSubmit, formState: { errors }, clearErrors, reset } =
useForm<IUserForm>({ //'resetField'
mode: "onChange",
resolver: yupResolver(userFormSchema)
});
useEffect(() => {
window.scrollTo({ top: 0, behavior: 'smooth' });
}, [])
//fetching list from backend.. <--------
useUpdateEffect( () => {
dispatch( getRolesList({companyId: user.companyId}) );
},[user.companyId])
useUpdateEffect(() => {
clearErrors()
reset();
}, [isFetching])
const onSubmit: SubmitHandler<IUserForm> = (data)=>{
const roles = rolesInput.map(role => parseInt(role.value))
if(roles){
dispatch(inviteUser({
companyId: user.companyId,
roles: roles,
firstName: data.firstName,
lastName: data.lastName,
email: data.email
}))
}else{
alert("Please assign roles")
}
}

React Hooks Form - onSubmit with data from useState

Hi :) I want to create checkout form with customer's address data, but onSubmit I would like to attach order data stored in useState (cartItems). For now, I've finished react hook form with onSubmit button that console.log only form inputs.
What is the best way to do that?
const Checkout = ({ emoneyPayment, setEmoneyPayment, cartItems }: CheckoutProps) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Order>();
I'm unfamiliar with React Hooks Form and TypeScript, but in JS / React you could wrap it in another hook:
const Checkout = ({ emoneyPayment, setEmoneyPayment, cartItems }: CheckoutProps) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Order>();
const [cartItems, setCartItems] = useState([])
// this function will be redefined every time cartItems or handleSubmit updates
const submitForm = useCallback(() => {
handleSubmit(cartItems)
}, [cartItems, handleSubmit])
return <div onClick={submitForm}>Submit</div>
}
UPDATE:
You will also need to pass in the cartItems to the handleSubmit. This seems to be the way to do so:
const Checkout = ({ emoneyPayment, setEmoneyPayment, cartItems }: CheckoutProps) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Order>();
const [cartItems, setCartItems] = useState([])
const onSubmit = (data) => {
const finalData = {...data, cartItems}
alert(JSON.stringify(finalData));
// do your actual submit stuff here
};
return <form onSubmit={handleSubmit(onSubmit)}>...formcomponents...</form>
}

Best practice for validating input while onChange inside React custom hook?

I built a custom hook to handle a form. One thing I'm having trouble with is calling the validation while the input value is changing.
I have four code snippets included. The second and third are just for context to show how the complete custom hook but feel free to skip them as I'm just curious about how to implement similar functionality from snippet 1 in snippet 4.
The reason I want to do this, in addition to calling it on submit, is that if the input value becomes ' ' I would like to display the error message and when a user started typing it would go away.
This was pretty simple when I wasn't using hooks I would just call a validate function after setState like this:
const validate = (name) => {
switch(name):
case "username":
if(!values.username) {
errors.username = "What's your username?";
}
break;
default:
if(!values.username) {
errors.username = "What's your username?";
}
if(!values.password) {
errors.username = "What's your password?";
}
break;
}
const handleChange = (e) => {
let { name, value } = e.target;
this.setState({ ...values,
[name]: value
}, () => this.validate(name))
}
So now using react hooks things are not as easy. I created a custom form handler that returns values, errors, handleChange, and handleSubmit. The form handler is passed an initialState, validate function, and a callback. As of now it looks like this:
import useForm from './form.handler.js';
import validate from './form.validation.js';
const schema = { username: "", password: "" }
export default function Form() {
const { values, errors, handleChange, handleSubmit } = useForm(schema, validate, submit);
function submit() {
console.log('submit:', values);
}
return (
<form></form> // form stuff
)
}
Here's the validation file. It's simple, it just requires values for two fields.
export default function validate(values) {
let errors = {};
if(!values.username) {
errors.username = "What's your username?";
}
if(!values.password) {
errors.password = "What's your password?";
}
return errors;
}
Now here is my form handler, where I'm trying to solve this problem. I have been trying different things around calling setErrors(validate(values)) in the useEffect but can't access the input. I'm not sure, but currently, the custom hook looks like this:
import { useState, useEffect, useCallback } from 'react';
export default function useForm(schema, validate, callback) {
const [values, setValues] = useState(schema),
[errors, setErrors] = useState({}),
[loading, setLoading] = useState(false); // true when form is submitting
useEffect(() => {
if(Object.keys(errors).length === 0 && loading) {
callback();
}
setLoading(false);
}, [errors, loading, callback])
// I see useCallback used for event handler's. Not part of my questions, but is it to prevent possible memory leak?
const handleChange = (e) => {
let { name, value } = e.target;
setValues({ ...values, [name]: value });
}
const handleSubmit = (e) => {
e.preventDefault();
setLoading(true);
setErrors(validate(values));
}
return { values, errors, handleChange, handleSubmit }
}
I'm not sure if it's a good idea to set other state (errors) while in a callback to set state (values) so created a code review
As commented; you can set errors while setting values:
const Component = () => {
const [values, setValues] = useState({});
const [errors, setErrors] = useState({});
const onChange = useCallback(
(name, value) =>
setValues((values) => {
const newValues = { ...values, [name]: value };
setErrors(validate(newValues));//set other state while in a callback
return newValues;
}),
[]
);
return <jsx />;
};
Or combine values and errors:
const Component = () => {
const [form, setForm] = useState({
values: {},
errors: {},
});
const onChange = useCallback(
(name, value) =>
setForm((form) => {
const values = { ...form.values, [name]: value };
const errors = validate(values);
return { values, errors };
}),
[]
);
const { errors, values } = form;
return <jsx />;
};

How to Handle Error using try catch using React State with Arrow functions

I am new to React, I am trying to implement some error validation with a react arrow function but got no luck all day.
The catch works and I can print the errors, but I dont know how to link the errors I am printing inside errorsHandler() to the other const where the form is for styling and warnings.
const errorsHandler= fieldErrors => {
if (fieldErrors) {
fieldErrors.forEach(err => {
const errorFieldName= err.field;
const errorDescription = err.message;
console.log('Field', errorFieldName, 'Description', errorDescription);
// Field name Description name already exists
});
}
};
export const defaultGroupModel = {
description: '',
active: true,
name: '',
}
const GroupFormModal = ({ editId, editGroup, onSave}) => {
const [groupState, setGroupState] = useState(defaultGroupModel);
useEffect(() => {
if (editGroup) {
setGroupState(editGroup);
}
}, [editGroup]);
const handleChange = ({ target: { value, name} }) => {
setGroupState({ ...groupState, [name]: value });
};
return ( (...) <Form onSubmit={e => onSave(e, groupState)} onReset={onReset}> (...);
};
const mapDispatchToProps = dispatch => ({
onSave: (e, group) => {
e.preventDefault();
if (group.id) {
dispatch(updateGroup(group));
} else {
dispatch(createGroup(group)).catch(error => {
errorsHandler(error.data.fieldErrors);
});
}
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(GroupFormModal);
I have tried to create an [errorState, setErrorState] and use useEffect inside the errorsHandler but get Invalid Hook. How can I have the handle inside the catch to be in the same context as the form ?
Thank you in advance
There are few things you can do here. First, use mapDispatchToProps to wrap inside dispatch your action's creators (without then and catch)
const mapDispatchToProps = dispatch =>({
updateGroup : group => dispatch(updateGroup(group)),
createGroup : group => dispatch(createGroup(group))
})
Now you can set an internal state to reflect those errors
const Component = ({ updateGroup, createGroup }) =>{
const [errors, setErrors] = useState(false)
const onSave = (group,e) =>{
createGroup(group)
.then(res => console.log('everything ok'))
.catch(err => setError(err) /* now you have the errors inside your component*/)
}
return <form onSubmit={ e => onSave(group,e)) }> /*...*/ </form>
}

Resources