Возможно, это не правильный вопрос. Но у меня проблема с хуком проверки пользовательских форм, который не читает входные значения, когда они обновляются через http-запрос.
Вот код CodeSandbox , если вы хотите попробовать его.
Это пользовательский крючок useValidatedForm
const [
profileFormData,
profileFormValidation,
validateProfileForm,
getProfileFormData
] = useValidatedForm(
profileFormInitialState,
profileFormValidationDefinitions
);
У меня есть состояние для profileFormInitialState
const [profileFormInitialState, setProfileFormInitialState] = useState({
firstName: ""
});
Я обновляю это состояние в запросе http (в настоящий момент фиктивный запрос http)
useEffect(() => {
const fn = "first name";
setProfileFormInitialState({
firstName: fn
});
setContent({ title: "My Personal Details" });
setLoading({ status: false });
}, []);
Это моя форма, которая передается в DOM. Входное значение устанавливается через состояние profileFormInitialState
.
const form = (
<>
<FormControl
key={"profileForm"}
submit={profileFormSubmit}
form={profileFormData}
validation={profileFormValidation}
>
<InputControl
autoComplete="off"
type="text"
name="firstName"
placeholder={profileFormInitialState.firstName}
value={profileFormInitialState.firstName}
onInput={e =>
setProfileFormInitialState({ firstName: e.target.value })
}
onChange={e => e.preventDefault()}
label="First Name*"
columns="2"
position="left"
>
<ErrorMsg map="required" msg="First Name is required" />
</InputControl>
<InputButton
modifier={"Button--profile"}
disabled={!profileFormValidation.valid}
buttonText="Update Profile"
type="submit"
/>
</FormControl>
</>
);
Ниже мой useValidatedForm
пользовательский крючок
import { useState } from "react";
import ValidaJS from "valida-js";
function stateFactory(fields) {
return Object.keys(fields).reduce((acc, key) => {
acc[key] = {
value: fields[key],
meta: {
touched: false,
dirty: false
}
};
return acc;
}, {});
}
function emptyErrorFactory(fields) {
return Object.keys(fields).reduce((acc, key) => {
acc[key] = [];
return acc;
}, {});
}
function rulesByNameFactory(descriptors, validators) {
const descriptorBy = descriptors.reduce((acc, descriptor) => {
acc[descriptor.type] = acc[descriptor.type];
acc[descriptor.name] = acc[descriptor.name]
? acc[descriptor.name].concat([descriptor])
: [descriptor];
return acc;
}, {});
return Object.keys(descriptorBy).reduce(
(acc, key) => {
acc[key] = ValidaJS.rulesCreator(validators, descriptorBy[key]);
return acc;
},
{ default: ValidaJS.rulesCreator(validators, descriptors) }
);
}
function getDataFromState(state) {
return Object.keys(state).reduce((acc, key) => {
acc[key] = state[key].value;
return acc;
}, {});
}
function extendsValidations(key, validation, newErrors = []) {
const newValidation = {
errors: {
...validation.errors,
[key]: newErrors
}
};
newValidation["valid"] = Object.keys(newValidation.errors).every(errorKey => {
return newValidation.errors[errorKey].length === 0;
});
return newValidation;
}
function onChangeHandlerByKey(
state,
key,
setState,
setValidation,
validation,
rulesBy
) {
return event => {
const newState = {
...state,
[key]: {
...state[key],
value:
event.currentTarget.type == "checkbox"
? event.currentTarget.checked
: event.currentTarget.value,
meta: {
...state[key].meta,
dirty: true
}
}
};
const newErrors = ValidaJS.validate(
rulesBy[key],
getDataFromState(newState)
).errors[key];
setState(newState);
setValidation(extendsValidations(key, validation, newErrors));
};
}
function onClickHandlerByKey(state, key, setState) {
return _ => {
setState({
...state,
[key]: {
...state[key],
meta: {
...state[key].meta,
touched: true
}
}
});
};
}
function formDataFactory(state, setState, setValidation, validation, rulesBy) {
return Object.keys(state).reduce((acc, key) => {
acc[key] = {
meta: state[key].meta,
input: {
value: state[key].value,
onClick: onClickHandlerByKey(
state,
key,
setState,
setValidation,
validation,
rulesBy
),
onChange: onChangeHandlerByKey(
state,
key,
setState,
setValidation,
validation,
rulesBy
)
}
};
return acc;
}, {});
}
const useValidatedForm = (
fields = {},
descriptors = [],
validators = ValidaJS.validators
) => {
const initialErrorsObj = emptyErrorFactory(fields);
const initialState = stateFactory(fields);
console.log("initial state = " + initialState.firstName.value);
const [state, setState] = useState(initialState);
console.log("state = " + state.firstName.value);
const [validation, setValidation] = useState({
valid: true,
errors: initialErrorsObj
});
const rulesBy = rulesByNameFactory(descriptors, validators);
const form = formDataFactory(
state,
setState,
setValidation,
validation,
rulesBy
);
const getData = () => getDataFromState(state);
const setData = data => setState(stateFactory(data));
const validate = () => {
const newValidations = ValidaJS.validate(
rulesBy.default,
getDataFromState(state)
);
setValidation({
...newValidations,
errors: { ...initialErrorsObj, ...newValidations.errors }
});
return newValidations.valid;
};
return [form, validation, validate, getData, setData];
};
export default useValidatedForm;
В функции useValidatedForm
проблема, с которой я сталкиваюсь, заключается в том, что когда я отправляю форму и эта функция вызывается, initialState
верен, он возвращает first name
, он используется как начальное значение для state
, но state
вернется в виде пустой строки и будет делать это до тех пор, пока я не введу ввод, а затем он обновится правильно. Так что я не совсем уверен, как заставить эту проверку работать, поскольку она полагается на значение state
и обновляет значение state
с помощью setState
? Любая помощь будет принята с благодарностью.