#javascript #reactjs #input #react-hooks #codesandbox
#javascript #reactjs #ввод #react-перехваты #codesandbox
Вопрос:
У меня есть загрузочный компонент, который создает скелет до тех пор, пока содержимое не будет отображаться через @trainline/react-skeletor
. В этом случае я создаю скелет для формы.
Во-первых, у меня есть CodeSandbox для тех, кто хочет увидеть, что происходит, и все компоненты, используемые для лучшего представления о решении.
Я также использую компонент на основе функций и хочу сохранить его таким образом, если только это невозможно сделать с помощью компонента на основе функций, я не хочу использовать компонент на основе классов для устранения этой проблемы.
У меня есть компонент, ProfileForm
который на данный момент содержит h3
и form
Форма выглядит следующим образом
const form = (
<>
<FormControl key={"profileForm"} submit={profileFormSubmit} form={profileFormData} validation={profileFormValidation}>
<InputControl autoComplete="off" type="text" name="emailAddress" placeholder="Email address" label="Email Address">
<ErrorMsg map="required" msg="Email is required"></ErrorMsg>
</InputControl>
</FormControl>
</>
)
FormControl
Компонент возвращает <form>
элемент
InputControl
Компонент возвращает элемент <label>
and <input>
ErrorMsg
Компонент возвращает <div>
Будет отображаться следующим образом.
<form class="Form " novalidate="">
<div class="InputControl">
<div>
<label for="emailAddress">Email Address</label>
<input type="text" placeholder="Email address" name="emailAddress" id="emailAddress" autocomplete="off" value=""></div>
<div class="InputControl--Errors">
</div>
</div>
</form>
Я создал фиктивный http-запрос, в котором я обновляю объект состояния с заголовком и формой выше.
const [content, setContent] = useState();
const ttl = 500;
/*simulate http request*/
useEffect(() => {
const timeout = setTimeout(() => {
setContent({ title: "My Personal Details", form });
}, ttl);
return () => {
clearTimeout(timeout);
};
}, []);
В моем возврате я передаю content
объект состояния в качестве реквизита (закомментированный код работает, но не создаст элемент загрузки скелета, который требуется в моем проекте
return (
<div className="ProfileForm">
<h2 style={{ color: "red" }}>Not working: Passing Form Down to Child</h2>
<ProfileFormContainer content={content} />
{/* <h2 style={{ color: 'green' }}>Working: Render Directly in return</h2>
{form}*/}
</div>
);
ProfileFormContainer
создает элемент skeleton, а затем передает реквизиты другому компоненту и возвращается в приведенном ниже фрагменте кода.
const Wrapper = createSkeletonElement('div', 'Loader Loader--InlineBlock ProfileForm--loading');
const H3 = createSkeletonElement('h3', 'Loader Loader--InlineBlock');
const DIV = createSkeletonElement('div', 'Loader Loader--Block ');
const ProfileFormLoader = (props) => {
return (
<Wrapper className="ProfileForm">
<H3 className="ProfileForm-title">{ props.title }</H3>
<DIV>
{props.form}
</DIV>
</Wrapper>
);
}
export default ProfileFormLoader;
Это отображается так, как ожидалось, однако, когда я пытаюсь ввести входные данные, это не обновляет значение входных данных. Мой вопрос в том, как мне обновить значение входных данных при вводе, когда входные данные передаются в качестве реквизита дочернему компоненту, как я сделал?
Любая помощь была бы высоко оценена
Ответ №1:
Вот что происходит: вы в основном отображаете только content
из useState
Вы имитируете свой HttpRequest, который будет обновляться content
до пустой формы
И затем вы больше никогда не обновляете content
, это все еще пустая форма из первого рендеринга.
Это работает, когда вы form
не включаетесь в content
, потому что form
при каждом рендеринге вычисляется фактическое profileFormData
значение.
Я предлагаю не использовать состояние для хранения узлов в вашем случае (и, вероятно, в большинстве других случаев). Возврат вашего http-запроса должен заполнить хранилище данных, из которого ваш шаблон мог бы считываться, но, учитывая тот факт, что ваша форма также нуждается в чтении из других источников, таких как текущее состояние ввода, безопаснее сохранить form
в рендере, где он будет обновляться при каждом рендере.
Комментарии:
1. Это имеет смысл, спасибо, что прояснили это. Возможно, я сделал это неправильно, но я поместил форму в рендеринг, но это означает, что она перекрывает мой загружаемый компонент. У меня есть этот CodeSandbox, чтобы показать, что я имею в виду — codesandbox.io/s/32ykv1xn26 Я неправильно реализовал то, что вы сказали выше?
2. Да, то, что вы сделали, работает. Причина, по которой ваш ввод остается видимым, заключается в том, что вы
.Loader
не скрываете его должным образом. Вы могли бы добавить ` amp; input { border-color: none; граница: отсутствует; цвет фона: прозрачный; amp;::заполнитель { color: transparent; } }` или что-то более чистое!3. На самом деле мне просто пришлось выполнить некоторую настройку при экспорте
createSkeletonProvider
с({ form, content }) => (form, content) === undefined,
помощью и обновлении фиктивного объекта с правильной структурой. Но спасибо, что указали мне правильное направление, опция css также может работать