5
\$\begingroup\$

I have a component, it's actually an entire screen in my application. This screen/component renders multiple other components. However, what it renders is conditional. Currently, I have an if statement, which decides which markup is returned. The only differences between the two markups is one additional <PDFPreview> component is added. I'm pretty sure this isn't the best way to go about this...

const SearchScreen = ({navigation}) => {
    const [ makeSelected, setMakeSelected ] = useState(null);
    const [ modelSelected, setModelSelected ] = useState(null);
    const [ yearSelected, setYearSelected ] = useState(null);
    const [ typeSelected, setTypeSelected ] = useState(null);

    const selectMakeHandler = newMakeData => {
        let makeId = newMakeData.id;
        setMakeSelected(makeId);
    }

    const selectModelHandler = newModelData => {
        let modelId = newModelData.id;
        setModelSelected(modelId);
    }

    const selectYearHandler = newYearData => {
        let yearId = newYearData.id;
        setYearSelected(yearId);
    }

    const selectTypeHandler = newTypeData => {
        let typeId = newTypeData.diagramTypeId;
        setTypeSelected(typeId);
    }


    if (typeSelected !== null)
    {
        return (
            <Layout style={styles.mainContainer1}>
                <Layout style={styles.pickerContainer}>
                    <MakePicker 
                    onSelectMake={selectMakeHandler}
                    />
                    <ModelPicker 
                    onSelectModel={selectModelHandler}
                    makeId={makeSelected}
                    />
                    <YearPicker 
                    makeId={makeSelected}
                    modelId={modelSelected}
                    onSelectYear={selectYearHandler}
                    />            
                    <DiagramTypePicker
                    makeId={makeSelected}
                    modelId={modelSelected}
                    modelYearId={yearSelected}
                    onSelectType={selectTypeHandler}
                    />
                    <Layout style={styles.previewContainer}>
                        <PdfPreview
                        makeId={makeSelected}
                        modelId={modelSelected}
                        modelYearId={yearSelected}
                        typeId={typeSelected}
                        />
                    </Layout>
                    <Layout style={styles.btnContainer}>
                        <Button 
                        onPress={() => navigation.navigate('Pdf')}
                        >
                        Download
                        </Button>
                    </Layout>
                </Layout>
                <Layout style={styles.adContainer}>
                    <Advertisement/>
                </Layout>
            </Layout>
        )
    } 
    else 
    {
        return (
            <Layout style={styles.mainContainer2}>
                <Layout style={styles.pickerContainer}>
                    <MakePicker 
                    onSelectMake={selectMakeHandler}
                    />
                    <ModelPicker 
                    makeId={makeSelected}
                    onSelectModel={selectModelHandler}
                    />
                    <YearPicker 
                    makeId={makeSelected}
                    modelId={modelSelected}
                    onSelectYear={selectYearHandler}
                    />            
                    <DiagramTypePicker
                    makeId={makeSelected}
                    modelId={modelSelected}
                    modelYearId={yearSelected}
                    onSelectType={selectTypeHandler}
                    />
                </Layout>
                <Layout style={styles.adContainer}>
                    <Advertisement/>
                </Layout>
            </Layout>
        )
    }
};


When a diagram is selected from the <DiagramTypePicker>, SearchScreen should re-render, every time, only now it should additionally render the PDF preview of the diagram type selected from <DiagramTypePicker>. If no preview is available for the diagram which was selected, I would like SearchScreen to instead show the original markup, the one without the PDF preview. I know with the useState() and useEffect() hooks I can watch the state of 'typeSelected' to control the re-render, but I'm still not sure if a huge 'if' statement with two different markups is the best way to go about this. Oh, and if the preview is unavailable the additional 'download' button would also be removed. Any advice? Comments? Questions or concerns? Thanks!

\$\endgroup\$
2
\$\begingroup\$

You can use ternary operator(?:) or logical AND(&&) operator and React Fragment to avoid this big if-else. The if-else with repetitive code violates DRY principle and should be avoided as any update to the code will be required at 2 different places which will be prone to error in case one is missed

const SearchScreen = ({ navigation }) => {
  ...
  return (
    <Layout style={typeSelected !== null ? styles.mainContainer1 : styles.mainContainer2}>
      <Layout style={styles.pickerContainer}>
        <MakePicker
          onSelectMake={selectMakeHandler}
        />
        <ModelPicker
          onSelectModel={selectModelHandler}
          makeId={makeSelected}
        />
        <YearPicker
          makeId={makeSelected}
          modelId={modelSelected}
          onSelectYear={selectYearHandler}
        />
        <DiagramTypePicker
          makeId={makeSelected}
          modelId={modelSelected}
          modelYearId={yearSelected}
          onSelectType={selectTypeHandler}
        />
        {typeSelected !== null &&
          <>
            <Layout style={styles.previewContainer}>
              <PdfPreview
                makeId={makeSelected}
                modelId={modelSelected}
                modelYearId={yearSelected}
                typeId={typeSelected}
              />
            </Layout>
            <Layout style={styles.btnContainer}>
              <Button
                onPress={() => navigation.navigate('Pdf')}
              >
                Download
                </Button>
            </Layout>
          </>
        }
      </Layout>
      <Layout style={styles.adContainer}>
        <Advertisement />
      </Layout>
    </Layout>
  )
};

Ternary Operator can be used as:

{typeSelected !== null
  ? <>
    <Layout style={styles.previewContainer}>
      <PdfPreview
        makeId={makeSelected}
        modelId={modelSelected}
        modelYearId={yearSelected}
        typeId={typeSelected}
      />
    </Layout>
    <Layout style={styles.btnContainer}>
      <Button
        onPress={() => navigation.navigate('Pdf')}
      >
        Download
        </Button>
    </Layout>
  </>
  : null
}

Note:

  • <></> is short for React.Fragment
  • Please try to use logical && in these cases for better readability purposes.

Hope it helps. Revert for any doubts

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.