【问题标题】:React TS - Passing props up the component treeReact TS - 向上传递组件树
【发布时间】:2020-06-11 00:59:41
【问题描述】:

我已经创建了表单元素,我可以通过不同的方式配置这些元素来创建表单。

这是一个例子:

<form>
  <Label htmlFor="name" name="Enter name:" />
  <InputWrapper>
    <Input id="name" name="name" />
  </InputWrapper>
  <CharacterLimit />
</form>

我想做的是在我的Input 组件上设置一个maxLengthrequired prop,这将导致我的Label 组件有一个红色星号(*)和我的@987654330 @ 组件显示我的Input 组件上设置的maxLength

这是我的Label 组件的样子:

interface ILabel {
  htmlFor: string;
  name: string;
  required?: boolean;
}

export const Label: React.FC<ILabel> = ({ htmlFor, name, required }) => {
  return (
    <StyledLabel htmlFor={htmlFor}>
      {name} {required && <StyledRequired>*</StyledRequired>}
    </StyledLabel>
  );
};

const StyledLabel = styled.label`
  font-weight: 600;
`;
const StyledRequired = styled.span`
  color: red;
`;

这就是我的 CharacterLimit 组件的样子:

interface ICharacterLimit {
  maxLength?: number;
}

export const CharacterLimit: React.FC<ICharacterLimit> = ({ maxLength }) => {
  return (
    <>
      {maxLength && (
        <StyledCharacterLimit>0 / {maxLength} Characters</StyledCharacterLimit>
      )}
    </>
  );
};

现在你可能想知道为什么我不把Label & CharacterLimit 我的 Input 组件内的组件和 以这种方式有条件地渲染它们。

好吧,我有另一个组件,如您所见,名为 InputWrapper,它用于设置 input 的“容器”的样式,我想将这个样式分开的原因是,我可以放一个例如,inputbutton 在容器内。

这里有一个插图可以更好地说明我的意思:

我怎样才能将道具从我的Input 组件传递到LabelCharacterLimit 组件?还是有其他方法可以在我的插图中实现相同的布局?

我在CodeSandBox上做了一个演示

【问题讨论】:

  • 您所有的子组件都在同一个文件中,那么问题出在哪里?
  • @JaredSmith 您能否举例说明如何使用它来获得相同的布局?我还在学习 React,所以我可以看到/玩一些实际的例子会很棒!
  • 我只是更深入地重新阅读了这个问题。我收回之前的评论。我认为现在您遇到的问题是由于试图使其过于通用(代码重用!)。使这些非常具体的一次性组件中的每一个都完全按照您想要的布局进行制作并没有什么害处(我仍然认为验证应该发生在表单级别并在道具中传递)。我认为尝试使您的样式包装器通用和可组合将比最终的价值更麻烦。最终的数据流会是这样的:
  • 表单模型 -> isValid?,回调到包装器 -> 使用回调呈现输入 -> input.onChange -> 作为道具传递的表单模型的回调 -> 更新模型 -> 得到验证 -> 通过 isValid ?回到包装器。

标签: reactjs typescript styled-components


【解决方案1】:

这不一定是答案,但评论太长了

类似这样的:

const FormModel = () => {
  const [formModel, setFormModel] = useState();
  const updateFormModel = name => value => setFormModel({
    ...formModel,
    { [name]: value }
  });
  return (
    <form>
      <InputWrapper onChange={updateForm("something")} isValid={validate(formModel)} />
    <form>
  );
};

const InputWrapper = ({ onChange, isValid }) => {
  // returns appropriate stuff, including 
  // <input onChange={e => onChange(e.currentTarget.value)} />
  // styled based on isValid prop. May also want to debounce
  // input, but whateves.
}

【讨论】:

  • 你介意分叉我的沙盒吗?我从能够玩和看到正在运行的东西中学习得更好。评论也将不胜感激:)
猜你喜欢
  • 1970-01-01
  • 2017-11-17
  • 2021-06-17
  • 2020-06-06
  • 1970-01-01
  • 2020-11-11
  • 2020-09-19
  • 2021-09-17
  • 2018-05-25
相关资源
最近更新 更多