【问题标题】:React anti-patterns - Splitting the render method into functionsReact 反模式 - 将渲染方法拆分为函数
【发布时间】:2022-08-17 03:22:05
【问题描述】:

将组件的渲染方法拆分为被视为反模式的函数吗?

我的意思是,如果 JSX 变得太大,我们可以完美地将其拆分为更多组件......

但是,下面的例子呢:

  /**
   * Renders the text inputs of the form.
   *
   * @returns {React.ReactElement} The text inputs.
   */
  const renderInputs = () => (
    <View style={styles.inputsContainer}>
      <UsernameInput
        ref={usernameInputRef}
        label={t(
          \"authentication.signUp.accountInformation.usernameInputLabel\"
        )}
        returnKeyType=\"next\"
        onChange={handleOnTextInputChange}
        onSubmitEditing={() => emailInputRef.current.focus()}
        containerStyle={commonStyles.textInputContainer}
      />

      <TextInput
        ref={emailInputRef}
        label={t(\"authentication.signUp.accountInformation.emailInputLabel\")}
        maxLength={MAX_EMAIL_LENGTH}
        textContentType=\"emailAddress\"
        keyboardType=\"email-address\"
        returnKeyType=\"next\"
        icon={{
          name: \"email\",
          type: \"material\",
          color: colors.scorpion,
        }}
        onChange={handleOnTextInputChange}
        onSubmitEditing={() => passwordInputRef.current.focus()}
        containerStyle={commonStyles.textInputContainer}
      />

      <PasswordInput
        ref={passwordInputRef}
        label={t(
          \"authentication.signUp.accountInformation.passwordInputLabel\"
        )}
        textContentType=\"newPassword\"
        returnKeyType=\"next\"
        onChange={handleOnTextInputChange}
        onSubmitEditing={() => repeatPasswordInputRef.current.focus()}
        containerStyle={commonStyles.textInputContainer}
      />

      <PasswordInput
        ref={repeatPasswordInputRef}
        label={t(
          \"authentication.signUp.accountInformation.repeatPasswordInputLabel\"
        )}
        textContentType=\"oneTimeCode\"
        returnKeyType=\"done\"
        blurOnSubmit
        onChange={handleOnTextInputChange}
        containerStyle={commonStyles.textInputContainer}
      />
    </View>
  );

  /**
   * Renders a button for continuing to the next screen.
   *
   * @returns {React.ReactElement} The *\'continue\'* button. 
   */
  const renderContinueButton = () => (
    <Button
      disabled={isContinueDisabled}
      uppercase
      mode=\"contained\"
      onPress={handleOnContinue}
      style={styles.button}
      labelStyle={globalStyles.buttonLabel}
    >
      {t(\"authentication.signUp.accountInformation.continueButton\")}
    </Button>
  );

  return (
    <View style={globalStyles.flexHorizontallyCenteredContainer}>
      {renderInputs()}
      {renderContinueButton()}
    </View>
  );
}

我应该避免在这里拆分代码吗?正如你所看到的......我正在为大多数“原子”部分使用自定义组件......以及两个内部辅助方法来使用相应的布局调整来呈现它们。

模式还是反模式?

    标签: javascript reactjs react-native design-patterns


    【解决方案1】:

    不,将 UI 抽象为不同的 JSX 组件并不是一种反模式。恰恰相反。推荐。

    有时,创建新的 JSX 组件可能更有意义。因此,而不是写

    <View style={globalStyles.flexHorizontallyCenteredContainer}>
          {renderInputs()}
          {renderContinueButton()}
    </View>
    

    您可以直接将 JSX 组件创建为 View 的子组件,如下所示。

    <View style={globalStyles.flexHorizontallyCenteredContainer}>
          <renderInputs />
          <renderContinueButton />
    </View>
    

    因为它们都是 JSX 组件。在这种情况下,通常期望 JSX 组件以大写字母开头并且不使用动词命名。因此,我建议将它们命名如下。

    const Inputs = () => {
     return (...)
    }
    const ContinueButton = () => {
      return (...)
    }
    

    虽然可以在另一个组件中定义组件,然后在主组件的渲染函数中创建它,但通常建议创建新文件。因此,InputsContinueButton 将被放置在一个新文件中,例如Inputs.jsContinueButton.js。您可以像往常一样导出它们并导入它们。这使得在不同的地方重用组件成为可能。

    【讨论】:

    • 另一方面,在包含数据的组件之外定义组件可能会导致阅读 props 钻取冗长而乏味。我决定使用辅助函数,因为我认为创建更多“原子/分子”组件是“不必要的”额外层的抽象。
    • 但我喜欢创建内部组件的想法,以前从未这样做过!
    • 把很多道具传给很多孩子的问题有时确实很不方便。这通常可以使用钩子来解决,例如如果您想从 API 调用中获取数据,请创建一个处理该问题的钩子。该钩子可以管理应用程序缓存,以防止多次获取数据。然后在您的组件中重用该钩子。这将消除传递道具的需要。当然,这并不总是可能的。如果您知道您不会在其他地方重用您的组件,那么创建嵌套组件是非常好的。
    • 也许,子渲染方法根本不是一种反模式……我认为当它们本身没有意义时,它们对于抽象我们的组件的小部分很有用。
    • 这些不是“子渲染”功能。 JSX 函数式组件仍然只是一个 JS 函数。像往常一样创建它会调用它的渲染函数。无需将它们称为普通的 JS 函数。
    【解决方案2】:

    我没有评论的业力 - 在这里发帖相对较新。

    我想谈谈大卫回答的最后一段:“虽然可以在另一个组件中定义组件然后在主组件的渲染函数中创建它,通常建议创建新文件。”(强调我的)

    这是不是可以在另一个组件内部定义一个组件。当您在另一个组件内部定义一个组件时,它会在每次渲染时反复销毁和重新创建。 Mark Erikson,Redux 的维护者之一,有一篇关于 React 渲染的精彩文章,并更多地讨论了为什么这是一个问题 here

    如果您想定义一个新组件,请在组件之外定义它,或者按照 David 的建议,在新文件中定义它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多