React 反模式 - 将渲染方法拆分为函数

React anti-patterns - Splitting the render method into functions

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

我的意思是,如果 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>
  );
}

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

模式还是反模式?

不,将 UI 抽象为不同的 JSX 组件并不是 anti-pattern。恰恰相反。值得推荐。

有时,创建新的 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。您可以照常导出它们并导入它们。这使得在不同地方重用组件成为可能。