Home > Software design >  React How to render a component after onClick the correct way?
React How to render a component after onClick the correct way?

Time:06-08

I'm having the following problem:

I have a Sidebar component in which I generated three buttons through the map() function. I put the buttons in a MUI Grid and applied styling on this grid.


const Sidebar = () => {

  const classes = useStyles()
  const navigate = useNavigate()


  return (
    <Grid container
      className={classes.containerStyling}
      direction="column">
      <Grid item className={classes.gridItemStyling}>
        {insurances.map((item, index) =>
          <Button
            key={index}
            className={classes.buttonListStyling}>
            <Grid container direction="column" className={classes.listItemStyling}>
              <Grid item>
                <Typography variant="h2">
                  {item.headline}
                </Typography>
              </Grid>
            </Grid>
          </Button>)}
      </Grid>
    </Grid>
  )
}

export default Sidebar

Now I would like to render a headline next to my sidebar depending on which button is clicked. The Headline will have it's own styling. I know i need a hook:

  const [hasRender, setRender] = useState(false);
  const onShow = React.useCallback(() => setRender(true), [])

<Button
            key={index}
            className={classes.buttonListStyling}
            onClick={onShow}>
</Button>


Then I have to check if 'visible' is true and render my Component.

{visible && <HeadlineContent/>}

The problem is that all the Sidebar styling is applied on the component HeadlineContent and I cannot figure out how to render the component outside the Grid so the correct styling is applied.

And how can I access the buttons text to dynamically create the headline with the same text?

I hope it is understandable.

CodePudding user response:

Since you mentioned you want to render your <HeadlineContent /> next to your sidebar, you're probably going to have a top level component which renders the two. This means that this top level component is responsible for holding your isVisible state, since it is set inside <Sidebar />, but used outside of it. Your <Sidebar /> should only contain simple callback for the buttons, which are going to be implemented in your top level component. What these callbacks do, is simply set the text you need to display in a local state in your top level component. You can also use the text as a flag to show the headline, if you don't want to implement a toggle for showing/hiding the headline. It would look something like below:

const Comp = () => {
    const [headline, setHeadline] = useState('');
    const onHeadlineChange = useCallback((newHeadline) => {
        setHeadline(newHeadline);
    }, [setHeadline]);

    return (
        <>
            <Sidebar onHeadlineChange={onHeadlineChange} />
            {headline && <HeadlineContent headline={headline} />}
        </>
    )
}

Notice that the example you provided:

const [hasRender, setRender] = useState(false);
const onShow = React.useCallback(() => setRender(true), [])

<Button
    key={index}
    className={classes.buttonListStyling}
    onClick={onShow}>
</Button>

does not need the useCallback hook, since the callback is not going to be passed down to any other child components.

If your goal is to have the <HeadlineContent /> component directly inside the <Sidebar /> component, you can move the state and the callback from my example above inside the <Sidebar /> component and remove the useCallback wrapper, since it won't be needed.

  • Related