【问题标题】:Recursion in react component that generates a form生成表单的反应组件中的递归
【发布时间】:2022-01-07 04:27:44
【问题描述】:

你好!

我目前正在尝试制作一个基于提供的对象生成的表单,这似乎对我扔给它的任何东西都有效。

也就是说,直到我找到一个嵌套对象。


问题:

一旦我达到了 if 条件 (typeof value === "object") 我想要一个隐藏的输入(这可行)。
然后我想进入我刚刚识别的那个对象,进入它可能包含的所有子对象,并按照与初始运行相同的标准生成输入。

function GenericForm(props: any) {
  var object = props.object;

  return (
    <div>
      <form>
        {Object.entries(object).map(([property, value]) => {
          let type: string = "";
          if (typeof value === "string") {
            type = "text";
          } else if (typeof value === "number") {
            type = "number";
          } else if (typeof value === "boolean") {
            type = "checkbox";
          } else if (value instanceof Date) {
            type = "date";
          } else if (typeof value === "object") {
            type = "hidden";
          }

          return [
            <label property={property} htmlFor={property}>
              {property}
            </label>,
            <input
              type={type}
              id={property}
              name={property}
              defaultValue={value as string}
              onChange={(newVal) => {
                object[property] = newVal.target.value;
              }}
            />,
          ];
        })}
      </form>
    </div>
  );
}
export default GenericForm;

我知道这很可能利用了某种递归,虽然我尝试使用递归来解决它,但我无法解决它。
此处粘贴的代码来自我尝试递归之前的代码,以便在我出错的地方有一张“干净的床单”。

编辑 1 - 添加对象结构信息

传递的对象应该是完全通用的,并允许将任何结构的对象传递给组件,目前它应该只评估属性的类型并从中创建一个输入元素。

我正在传递的当前对象之一具有以下 JSON 架构

{
    "id": "XYZ1",
    "type": "twilio-api",
    "sid": "someSID",
    "from": "+phonenumberhere",
    "name": "TWILIO SMS",
    "credentials": {
        "token": "someapitoken"
    }
}

上面的对象当前呈现如下:

【问题讨论】:

  • 你能否分享object 的样子(以及它的预期输出)?
  • 请不要在您的帖子中添加太多分散注意力的粗体斜体,并且请使用正确的大小写和拼写。这两者都使您更容易阅读您的问题并为您提供帮助。此外,SO 的社区标准强烈反对在问题(例如问候和谢谢)中“吹毛求疵”。
  • @NickParsons 在帖子中添加了关于对象模式的编辑。预期的输出将是一个带有隐藏输入的凭证标签,然后在令牌下方,其输入由类型定义,如前所述,这应该到对象结构的末尾,不限于“2 级”对象链接对象
  • @TJCrowder 因为英语不是我的母语,对于我所犯的任何拼写错误,我深表歉意,我确实会在发布前使用我的自动更正来修复,所以我希望它不会太糟糕.有毛病,我会相应地更新我的帖子:)
  • @robskaar - :-) 我向你保证,你写英语比我写任何其他语言都要好。对于母语人士来说,真正跳出来的一件事是“I”总是大写,从不小写(不是“i”)。编码愉快!

标签: javascript reactjs typescript forms recursion


【解决方案1】:

假设你有一个Input 组件:

  function Input = ({ name, type, value }) => {
    // most of your code can fit here
    return <input name={name} type={type} value={value} />
  }

您可以使用您的代码版本,我使用上面的简化版本以使我们的讨论更容易。有了它,我们可以设计一个InputList 组件:

  function InputList = ({ object }) => {
    console.log('list', object)
    return (
      <div>
        {Object.entries(object).map(([property, value]) => {
           if (typeof value === "object") {
             return <InputList object={value} />
           } else {
             return <Input name={property} />
           }
        })}
      </div>
    )
  }

您可以看到在这个InputList 内部,再次调用了InputList,所以这就是您要查找的递归。当对象中不再有对象时,递归停止。

注意:React 需要 valueonChange 来驱动任何 input 框。否则,它们只会表现得像本机输入。但这不是这个问题的一部分。

【讨论】:

  • 感谢您的回答,这似乎太简单了,但很明显,如果满足条件,我只需返回另一个组件。我现在刚下班。明天某个时候会试试这个,如果它解决了这个问题,我当然会把它标记为答案,同时我已经赞成你的建议,因为它看起来已经很直观:)
  • 不是问题@robskaar,有几种不同的递归方式。在更教科书的版本中,我们只会设计一个名为Input的组件,但在测试时我发现它太乱了。最好我们可以看到每个简单的输入有效,然后输入列表有效,一次一个步骤。
  • 我不得不做一些调整,但它最终完美运行。简单而直观的解决方案,但我一直专注于尝试使其成为组件返回之上的递归函数并在组件返回部分中实现它,所以我什至没有考虑将其移出并调用的解决方案满足条件时的组件。我仍然不得不对其进行一些调整,但最终这最终解决了问题的大部分,我现在有一个通用的形式,我可以扔任何物体。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多