通过使用React Hooks将输入传递到子组件中来更新输入值

时间:2019-03-26 09:46:14

标签: javascript reactjs input react-hooks 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><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创建骨骼元素,然后将道具向下传递到另一个Component中,并在下面的代码片段中返回。

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 个答案:

答案 0 :(得分:1)

这是发生了什么: 您基本上只显示content

中的useState

您模拟自己的httpRequest,这会将content更新为一个空表格

然后您再也不会更新content,它仍然是第一个渲染的空白表格。

当您将form保留在content中时,它会起作用,因为form在每次渲染时都会使用实际的profileFormData进行评估。

我建议在您的情况下(可能还有其他大多数情况下)不使用状态存储节点。您的http请求的返回应填充一个您的模板可以读取的数据存储,但是鉴于您的表单也需要从其他来源读取(例如当前输入状态),因此保留form更为安全在渲染器中,它将在每个渲染器中更新。