我创建了一个名为useForm
的自定义钩子。 useForm
采用一个初始对象,该对象使用useState
设置为自己的状态。它返回此状态。该钩子还具有其他功能,例如getData
和submitData
来处理数据检索/发布。它还返回设置状态的handleOnChange
函数。
我在名为GeneralInformationForm
的表单元素中使用此钩子。此表单具有几个输入,数据检索和发布功能(传递给该钩子以便可以处理错误)。
输入的状态与从useForm
钩返回的状态相关联,而我输入的onChange方法是从钩返回的handleOnChange
函数。
我的问题是: 当我无法直接设置状态时,如何编写测试以查看表单是否正确提交和检索值?
我应该在输入上触发多个onChange
事件以这种方式设置状态吗?我应该以不同的方式处理表格吗?
该钩子存在的原因是在表单之间重用逻辑,特别是onChange和错误设置逻辑。
我正在使用Jest和酶。
GeneralInformationForm.tsx
:
const GeneralInformationForm = (props: IProps) => {
useEffect(() => {
if (props.partnerId) handleGetData();
}, [props.partnerId]);
const getData = async () => {
if (!props.partnerId) return initialState;
const response = await getPartner(props.partnerId);
initialState.name.value = response.data.Name;
initialState.uuid.value = response.data.UUID;
initialState.token.value = response.data.Token;
initialState.isAutoClick.value = response.data.IsAutoClickEnabled;
return initialState;
};
useEffect(() => {
if (props.isSubmitted) handleOnSubmit();
}, [props.isSubmitted]);
const submitData = async () => {
const postObject = {
Name: state.name.value,
Token: state.token.value,
IsAutoClickEnabled: state.isAutoClick.value,
};
if (props.partnerId) {
return editPartner(props.partnerId, postObject, []);
}
const response = await createPartner(postObject, []);
props.setPartnerId(response.data.UUID);
return response;
};
const {
state,
handleGetData,
handleOnChange,
handleOnSubmit,
} = useForm(initialState, submitData, props.resetSubmitted, getData);
return (
<div className={styles.formContainer}>
<TextField
name="name"
label="Partner name"
value={state.name.value}
onChange={handleOnChange}
margin="normal"
error={Boolean(state.name.error)}
helperText={state.name.error}
variant="outlined"
/>
<TextField
name="uuid"
label="Partner UUID"
disabled
value={state.uuid.value}
onChange={handleOnChange}
margin="normal"
error={Boolean(state.uuid.error)}
helperText={state.uuid.error}
variant="outlined"
/>
<TextField
name="token"
label="Token"
disabled={!props.partnerId}
value={state.token.value}
onChange={handleOnChange}
margin="normal"
error={Boolean(state.token.error)}
helperText={state.token.error}
variant="outlined"
/>
<FormControlLabel
className={styles.checkbox}
control={
<Checkbox checked={state.isAutoClick.value} onChange={handleOnChange} name="isAutoClick" />
}
label="Enable Auto-click"
/>
{!props.partnerId && (
<Button
variant="contained"
onClick={handleOnSubmit}
>
Create Partner
</Button>
)}
</div>
);
};
export default GeneralInformationForm;
const initialState = {
name: { value: '', error: '' },
uuid: { value: 'automatically generated', error: '' },
token: { value: 'automatically generated', error: '' },
isAutoClick: { value: false, error: '' },
};
useForm.tsx
:
function useForm(initialState: any, submitData: any, resetSubmitted: any, getData: any) {
const [state, setState] = useState(initialState);
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name } = event.target;
const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
setState((prevState: any) => ({
...prevState,
[name]: { value, error: '' },
}));
};
const handleOnSubmit = async () => {
const response = await submitData(state);
if (response === null) {
// There was no partnerId present so the form could not submit correctly
}
if (response.status === 400) {
handleErrors(response.data);
}
// if (response.status === 200) {
// handleGetData();
// }
resetSubmitted();
};
const handleGetData = async () => {
const retrievedData = await getData();
setState({ ...retrievedData });
};
const handleErrors = (errors: any) => {
// Set the errors to the state
};
return {
setState,
state,
handleOnChange,
handleOnSubmit,
handleGetData,
};
}