Home > database >  Conditionally Rendering Components From An Array of Components
Conditionally Rendering Components From An Array of Components

Time:04-21

I have 3 cards I want to render on the screen all with a similar layout. What is this pattern called when we have a component as a value?

const steps = [
  {
    label: "Order details",
    component: OrderDateStep,
  },
  {
    label: "Driver details",
    component: OrderDriverStep,
  },
  {
    label: "Acknowledgements",
    component: OrderAcknowledgementStep,
  },
];

Additionally I keep running into an issue when these are conditionally rendered. I want to wait until stripe has initialised before displaying the form. However, I get an error Error: Rendered more hooks than during the previous render.. I know I can just add the different components but that isn't very scalable. Is there another way I can achieve this re-usable pattern without running into this issue with the number of hooks changing? Why does using step[x].component() change the number of hooks where just using the component does not?

  {stripe && (
    <Elements
      stripe={stripe}
      options={{
        clientSecret: paymentIntent?.client_secret,
      }}
    >
      {steps.map((step, index) => {
        return (
          <Box
            key={step.label}
            sx={{
              mt: 3,
            }}
          >
            <Box sx={{ my: 2 }}>
              <Typography variant="h5">{step.label}</Typography>
            </Box>
            {step.component()}
          </Box>
        );
      })}
      <Box sx={{ display: "flex", justifyContent: "end" }}>
        <Button variant="contained" onClick={submitForm}>
          Submit
        </Button>
      </Box>
    </Elements>
  )}

CodePudding user response:

If you want to make sure something is filled, or rendered, before displaying other data in react, you can just do

{
loadedVariable ? 
<div>
......
</div>
:null
}

If your question is not fully answered by the point i get home i'll be happy to help you further.

CodePudding user response:

Add one more conditionally into your render component to make sure that steps had filled:

{stripe && steps.length && (
<Elements
  stripe={stripe}
  options={{
    clientSecret: paymentIntent?.client_secret,
  }}
>
  {steps.map((step, index) => {
    return (
      <Box
        key={step.label}
        sx={{
          mt: 3,
        }}
      >
        <Box sx={{ my: 2 }}>
          <Typography variant="h5">{step.label}</Typography>
        </Box>
        {step.component()}
      </Box>
    );
  })}
  <Box sx={{ display: "flex", justifyContent: "end" }}>
    <Button variant="contained" onClick={submitForm}>
      Submit
    </Button>
  </Box>
</Elements>
)}
  • Related