【问题标题】:What is the proper way of implementing form input validation with stateless components使用无状态组件实现表单输入验证的正确方法是什么
【发布时间】:2016-09-19 10:41:01
【问题描述】:

所以我最近开始使用 react-native,我显然希望使用最佳实践来处理我的应用程序。这就是为什么我决定使用 redux 并按照建议编写无状态的函数式组件。

一旦我习惯了它并建立了一些标准,它在一段时间内工作得很好:我编写了一个功能组件,映射状态并分派到它的道具,并有一个商店来跟踪事情的进展情况并由 @987654321 注入@。

一旦我开始验证我的表单输入组件,事情就变得复杂了。假设我想要一个可以验证其输入并在出现问题时显示错误的组件。我显然可以为此向我的全局商店添加一些状态,但我不想在我的应用程序中使用的每个输入都在我的全局商店中占有一席之地。这可能与所教授的使用 redux 的内容形成对比,但我感觉我想要的并不是那么不切实际。

所以举一个我想要的例子:

const Input = ({ error }) => {
  let style = styles.input;
  const onChange = (val) => {
    // change the error here, say
    if(val === 'test') error = null;
    else error = 'must be test';
  };
  if (error) {
    style = styles.inputError;
  }
  return (
    <TextInput
      style={style}
      onChangeText={onChange}
    />
  );
};

但我不想将错误与全局状态联系起来。

这是不是问的太多了,还是我忽略了让Input 自我刷新的方法(我根本无法获得this)?

我知道这更像是一个哲学问题,因为有一个明显的解决方案是为您的组件创建 ES6 类并使用setState。我最感兴趣的是听到一些解决这个问题的方法以及是否存在问题,或者我只是太固执了。 :)

【问题讨论】:

  • 在父非功能组件中使用反应状态是一种解决方案吗?否则,如果您想控制输入,则不应使用功能组件。
  • 我没有非功能性组件。如果我想控制我的输入,是否有理由不使用功能组件?如果我想让父母设置我的组件输入怎么办?有没有办法在保持父母功能的同时做到这一点?
  • 1 。保持它在你的 Redux 状态, 2。具有反应状态和 onChange 处理程序的非功能组件 3 。仅在提交时验证输入,不像您那样 onChange={myHandler}
  • 有效点,所以最简单的方法是让 ES6 类可以控制自己的状态并使用它。不幸的是,提交时不能进行输入验证。
  • 所以,是的,您应该为此使用非功能性的,这种方法在性能方面并没有太多遗漏

标签: javascript reactjs react-native redux


【解决方案1】:

好的,我提到这几乎是一个元问题,但对我来说是一个重要的问题,因为我在摆弄它时学到了很多东西。

希望我学到的知识能帮助遇到同样问题的人,并节省他用如此少的在线资源研究这个主题所需的时间:

  1. 您不能也可能不应该能够从内部访问您的纯控件。
  2. 如果您确实必须将控件创建为 ES6 类并访问 this,那么即使您的 linter 也不会再抱怨了,因为这是很好的用例,所以在某些情况下可以扩展 Component .

使用这两个结论的控件示例如下:

class Input extends Component {
  render() {
    let style = styles.input;
    const error = this.state && this.state.error;
    const onChange = (val) => {
      if (val === 'test') this.setState({ error: null });
      else this.setState({ error: 'test required' });
    };
    if (error) {
      style = styles.inputError;
    }
    return (
      <TextInput
        style={style}
        onChangeText={onChange}
      />
    );
  }
}

现在,由于我很固执,我又学到了一件事:只用纯组件就可以做到。就像我在某处的 cmets 中所说的那样,可以创建一个本地存储,将您的组件包装在 Provider 中,并以您在使用功能组件时习惯的方式连接到它。我不确定它会有多大用处,但我会提供示例:

const localStore = createStore(
  (state = [], obj) => (obj ? { errorMessage: obj.error } : state),
  { errorMessage: null },
);

const inputWithStore = ({ error }) => {
  let style = styles.input;
  const onChange = (val) => {
    if (val === 'test') localStore.dispatch({ type: 'unused', error: null });
    else localStore.dispatch({ type: 'unused', error: 'test required' });
  };
  if (error) {
    style = styles.inputError;
  }
  return (
    <TextInput
      style={style}
      onChangeText={onChange}
    />
  );
};

const mapStateToProps = (state) => ({ error: state.errorMessage });

const InputWithStore = connect(mapStateToProps)(inputWithStore);

const Input = () =>
(
  <Provider store={localStore}>
    <InputWithStore />
  </Provider>
);

我仍然会很高兴听到有关这些的其他方法和 cmets。谢谢。

【讨论】:

  • 我是同一个决策分支,即使我喜欢你的想法,听听其他案例也会很有趣。
  • 嗯,有趣的评论,不幸的是可能没有很多人偶然发现这一点,所以我发送了我未来的自我给你第二个意见:事实上你可能希望你的常用组件在结束。因此,即使您的输入本身也是愚蠢的,它会将所有内容都传递给它。你绝对需要有一个有状态的父组件(所以你应该忽略我上面的固执)。在上面的示例中,您的父组件将是表单。它将处理您的哑输入组件呈现的逻辑。没有深入的解释,但我希望它有意义。
  • 我同意并感谢您的评论。 atm 没有任何其他答案,但我投了赞成票,因为我喜欢这个思路。会跟进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 2021-05-21
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多