Обновление входного значения с помощью ввода, переданного в дочерний компонент с помощью перехватов React

#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 также может работать