title: How to handle React components that have intensive logic?
body: <h2>Template Question</h2>
  
  <h3>The Problem</h3>
  
  <p>Hey guys!</p>
  
  <p>Recently I've been noticing some very logic-intensive react components being created in the application I work in, and this components usually have dozens of line that I call "setup logic" (variables that needs to be set before I render my component). Some of this stuff can be:</p>
  
  <ul>
  <li>Sending a request to the translation service to retrieve the required translated strings for that component</li>
  <li>Creating derived data from states, such as:
  
  <ul>
  <li>whether or not to show a component given a feature flag from the API</li>
  <li>The percentage of a progress bar given an initial and final value received by the API</li>
  </ul></li>
  <li>Getting the currentUser</li>
  <li>Getting the default brand colours and font sizes</li>
  <li>Mutations/Queries that will be executed when the user clicks on a button</li>
  <li>Mapping all this info to styled components and child components</li>
  </ul>
  
  <p>This begs the question of "Are we doing too much in these components?"</p>
  
  <p>Undoubtedly yes, but how exactly do we break this apart? Where do we draw the line?</p>
  
  <p>Ah, and a heads up, this is our setup currently:</p>
  
  <p><strong>Stack info:</strong></p>
  
  <p>Frontend: React</p>
  
  <p>API: GraphQL</p>
  
  <h3>Possible Solution</h3>
  
  <p>Separating the setup logic (the getters, mappers and queries) from the presentation logic (the JSX).</p>
  
  <p><strong>Question 1.</strong> Should there be a component that's sole responsibility is to serve the presentation component with its logic?</p>
  
  <p><strong>Question 2.</strong> Should this be a component at all or should this logic be served by the graphQL API? How coupled should the GraphQL be to the React component?</p>
  
  <h3>Sample Code</h3>
  
  <p>This is an example that illustrates the issue:</p>
  
  <pre class="lang-js prettyprint-override"><code>// 30 lines of *import*
  // ...
  
  const MyForm = ({
    onSubmit,
    initialValues,
    children,
    loading,
    isCreating,
    cycleId,
    permissions,
    otherPermissions,
    showWeightBalance,
    balance,
  }) =&gt; {
    const { t } = useTranslation();
    const currentUser = useCurrentUser();
    const cycle = useCycle({ id: cycleId });
    const canUpdateFields =
      isCreating || (permissions &amp;&amp; permissions.update);
    const canUpdateContributors =
      isCreating ||
      (permissions &amp;&amp; permissions.updateContributors);
    const canReassignResponsible =
      isCreating ||
      (permissions &amp;&amp; permissions.reassignResponsible);
    const canUpdateWeight =
      isCreating ||
      (otherPermissions &amp;&amp;
        otherPermissions.updateWeight);
    const canShowContributorsInput =
      isCreating ||
      (permissions &amp;&amp; permissions.showContributorsInputOnForm);
  
    return (
      &lt;Form
        initialValues={{
          name: {},
          description: {},
          type: {
            kind: kind.NUMBER,
            direction: direction.ASC,
          },
          baseValue: null,
          target: null,
          unit: null,
          weight: 1,
          progressCalculus: false,
          responsible: null,
          contributors: [],
          tasks: [],
          scale: null,
          ...initialValues,
        }}
        onSubmit={onSubmit}
        key={JSON.stringify(initialValues)} // This is made to reset the form when new initial values get loaded, should be enableReinitialize but richtexteditor wouldn't reset
      &gt;
        {formProps =&gt; (
          &lt;Fragment&gt;
            &lt;FormFieldTextTranslations
              name="name"
              label={t('yml_path')}
              subtitle={t('yml_path')}
              placeholder={t('yml_path')}
              locales={locale.availableLocales()}
              validate={[
                requiredTranslation(t('yml_path')),
              ]}
              disabled={loading || !canUpdateFields}
            /&gt;
            &lt;FormFieldRichTextTranslations
              name="description"
              label={t('yml_path')}
              subtitle={t('yml_path')}
              placeholder={t(
                'yml_path',
              )}
              locales={locale.availableLocales()}
              optional
              hideToolbar
              minimumLines={4}
            /&gt;
            &lt;FormFieldGroup
              name="type"
              label={t('yml_path')}
              validate={[required('yml_path')]}
            &gt;
              &lt;Layout display="flex" flexWrap="wrap"&gt;
                &lt;FormFieldRadio
                  mr="px32"
                  mb={['px8', 'none']}
                  disabled={loading || !isCreating}
                  name="type"
                  value={{
                    kind: kind.NUMBER,
                    direction: direction.ASC,
                  }}
                  label={(checked, disabled, error) =&gt; (
                    &lt;RadioCard
                      iconProps={{
                        iconName: 'chart-line',
                        solid: true,
                        fontSize: '20px',
                      }}
                      text={t(
                        'yml_path',
                      )}
                      checked={checked}
                      disabled={disabled}
                      error={error}
                    /&gt;
                  )}
                /&gt;
                &lt;FormFieldRadio
                  mr="px32"
                  mb={['px8', 'none']}
                  disabled={loading || !isCreating}
                  name="type"
                  value={{
                    kind: kind.NUMBER,
                    direction: direction.DESC,
                  }}
                  label={(checked, disabled, error) =&gt; (
                    &lt;RadioCard
                      iconProps={{
                        iconName: 'chart-line-down',
                        solid: true,
                        fontSize: '20px',
                      }}
                      text={t(
                        'yml_path',
                      )}
                      checked={checked}
                      disabled={disabled}
                      error={error}
                    /&gt;
                  )}
                /&gt;
                &lt;FormFieldRadio
                  mr="px32"
                  mb={['px8', 'none']}
                  disabled={loading || !isCreating}
                  name="type"
                  value={{
                    kind: kind.KEEP,
                    direction: formProps.values.type.direction,
                  }}
                  label={(checked, disabled, error) =&gt; (
                    &lt;RadioCard
                      iconProps={{
                        iconName: 'chart-keep',
                        solid: true,
                        fontSize: '20px',
                      }}
                      text={t('yml_path')}
                      checked={checked}
                      disabled={disabled}
                      error={error}
                    /&gt;
                  )}
                /&gt;
                &lt;FormFieldRadio
                  mb={['px8', 'none']}
                  disabled={loading || !isCreating}
                  name="type"
                  value={{
                    kind: kind.BINARY,
                    direction: null,
                  }}
                  label={(checked, disabled, error) =&gt; (
                    &lt;RadioCard
                      iconProps={{
                        iconName: 'check',
                        solid: true,
                        fontSize: '20px',
                      }}
                      text={t(
                        'yml_path',
                      )}
                      checked={checked}
                      disabled={disabled}
                      error={error}
                      tooltip={t(
                        'yml_path',
                      )}
                    /&gt;
                  )}
                /&gt;
              &lt;/Layout&gt;
            &lt;/FormFieldGroup&gt;
            {formProps.values.type.kind === kind.NUMBER &amp;&amp;
              formProps.values.type.direction === direction.ASC &amp;&amp; (
                &lt;AscendingForm
                  formProps={formProps}
                  loading={loading}
                  canUpdateFields={canUpdateFields}
                  canUpdateWeight={canUpdateWeight}
                  showWeightBalance={showWeightBalance}
                  balance={balance}
                  isCreating={isCreating}
                /&gt;
              )}
            {formProps.values.type.kind === kind.NUMBER &amp;&amp;
              formProps.values.type.direction === direction.DESC &amp;&amp; (
                &lt;DescendingForm
                  formProps={formProps}
                  loading={loading}
                  canUpdateFields={canUpdateFields}
                  canUpdateWeight={canUpdateWeight}
                  showWeightBalance={showWeightBalance}
                  balance={balance}
                  isCreating={isCreating}
                /&gt;
              )}
            {formProps.values.type.kind === kind.KEEP &amp;&amp; (
              &lt;KeepForm
                loading={loading}
                canUpdateFields={canUpdateFields}
                canUpdateWeight={canUpdateWeight}
                showWeightBalance={showWeightBalance}
                balance={balance}
                isCreating={isCreating}
              /&gt;
            )}
            {formProps.values.type.kind === kind.BINARY &amp;&amp; (
              &lt;BinaryForm
                loading={loading}
                canUpdateWeight={canUpdateWeight}
                showWeightBalance={showWeightBalance}
                balance={balance}
                isCreating={isCreating}
              /&gt;
            )}
            {cycle &amp;&amp;
              (cycle.allowCustomScore ||
                cycle.allowScale) &amp;&amp;
              formProps.values.type.kind !== kind.BINARY &amp;&amp; (
                &lt;FormFieldGroup
                  name="progressCalculus"
                  label={t('yml_path')}
                  validate={[
                    required(t('yml_path')),
                  ]}
                &gt;
                  &lt;FormFieldRadio
                    name="progressCalculus"
                    mb="px4"
                    label={t(
                      'yml_path',
                    )}
                    disabled={loading || !isCreating}
                    value={false}
                  /&gt;
                  {cycle.allowCustomScore &amp;&amp; (
                    &lt;FormFieldRadio
                      name="progressCalculus"
                      mb="px4"
                      label={t(
                        'yml_path',
                      )}
                      disabled={loading || !isCreating}
                      value={ProgressCalculusEnum.customScore}
                    /&gt;
                  )}
                  {cycle.allowScoreScale &amp;&amp; (
                    &lt;Fragment&gt;
                      &lt;FormFieldRadio
                        name="progressCalculus"
                        mb="px4"
                        label={t(
                          'yml_path',
                        )}
                        disabled={loading || !isCreating}
                        value={ProgressCalculusEnum.scale}
                      /&gt;
                      &lt;ScaleRadioHelperNegativeMargin&gt;
                        &lt;FieldHelper
                          message={t(
                            'yml_path',
                          )}
                          iconName="info-circle"
                        /&gt;
                      &lt;/ScaleRadioHelperNegativeMargin&gt;
                    &lt;/Fragment&gt;
                  )}
                &lt;/FormFieldGroup&gt;
              )}
            {isCreating &amp;&amp;
              cycle &amp;&amp;
              cycle.allowScoreScale &amp;&amp;
              formProps.values.type.kind === kind.NUMBER &amp;&amp;
              formProps.values.progressCalculus ===
                ProgressCalculusEnum.scale &amp;&amp; (
                &lt;ScoreScaleForm
                  name="scale.partitions"
                  formProps={formProps}
                /&gt;
              )}
            &lt;FormFieldSelectContract
              name="responsible"
              label={t('yml_path')}
              placeholder={t(
                'yml_path',
              )}
              filter={{ active: true }}
              validate={[
                required(
                  t('yml_path'),
                ),
              ]}
              disabled={loading || !canReassignResponsible}
              allowClear
            /&gt;
            &lt;AssignToMeWrapper&gt;
              &lt;Button
                kind="primary"
                size="adaptative"
                appearance="text"
                onMouseDown={() =&gt; {
                  setTimeout(
                    () =&gt;
                      formProps.setFieldValue('responsible', {
                        key: currentUser.id,
                        label: currentUser.name,
                      }),
                    20,
                  );
                }}
              &gt;
                {t('assign_to_me')}
              &lt;/Button&gt;
            &lt;/AssignToMeWrapper&gt;
            {canShowContributorsInput &amp;&amp; (
              &lt;FormFieldSelectContract
                name="contributors"
                mode="multiple"
                label={t('yml_path')}
                placeholder={t(
                  'yml_path',
                )}
                filter={{ active: true }}
                optional
                disabled={loading || !canUpdateContributors}
              /&gt;
            )}
            {isCreating &amp;&amp; (
              &lt;FormFieldGroup
                name="tasks"
                label={t('yml_path')}
                optional
              &gt;
                &lt;TasksForm name="tasks" tasks={formProps.values.tasks} /&gt;
              &lt;/FormFieldGroup&gt;
            )}
            &lt;Layout mt="px40"&gt;{children(formProps)}&lt;/Layout&gt;
          &lt;/Fragment&gt;
        )}
      &lt;/Form&gt;
    );
  };
  
  export default MyForm;
  </code></pre>