React reusable components?

Hey guys, trying to understand the best practices for creating reusable components when adding extra props. I’m not quite sure when to use the rest operator for bring in any other props the component needs.

Here, I am creating two buttons from the same component, but adding an extra prop and checking if that prop exists, then rendering an extra div. I don’t think this is right and I need to use the rest operator for this to be right? Any guidance is much appreciated.

import Button from '../common/button/Button';

function App() {
  return (
    <div className="App">
      <Button text="btn1" link="https://www.google.com" class="btn1" />
      <Button text="btn2" link="https://www.facebook.com" class="btn2" extra="testDiv" />
    </div>
  );
}
import React from 'react';

const Button = (props) => {
  return (
    <div className={`Button ${props.class}`}>
      <button>
        <a target="_blank" href={props.link}>
          {props.text}
        </a>
      </button>
      {props.extra && <div>{props.extra}</div>}
    </div>
  );
};

export default Button;

1 Like

In general it is not good idea. You want button to stay a button, meaning conditional rendering should be applied to it and be essential part of it. I’m really not sure about inserting anchor inside a button and conditionally rendering something outside the button (as well as wrapping button in a block element in the first place). This way would be more correct in my opinion:

const Button = ({ label, action, icon, classList }) => {
  return action.type === 'href'
    ? <a href={action.payload} className={classList.join(' ')} role="button">{label}</a>
    : <button type="button" onClick={action.payload} className={classList.join(' ')>{label}</button>;
};
1 Like

And how would you call both buttons here?

I’m confused how you would access action.type / action.payload.

Ahhh never mind. Thanks a lot. Still confused on when I would be using the spread operator if I had a ton of props and not sure which had to be used.

You would call them the same way:

<Button label="Click Me" classList={['primary-btn']} action={{ type: 'href', payload: 'https://google.com' }} />
<Button label="I Feel Lucky" classList={['secondary-btn']} action={{ type: 'function', payload: handleClick }} />
1 Like

It’s hard for me to imagine the case where you would use spread operator for component like this. The only place where you would use it is higher order components really:

const Page = ({ Child, props }) => {
  const additionalProps = 42;
  return <Child {...props, additionalProps} />
}
1 Like

I would also say that you should probably know exactly what props a component expects to use so the spread operator isn’t always applicable.

Especially if you’re following best practices and using PropTypes.

1 Like

It’s just that professionally the codebase I ran into they were using it by accepting whatever prop you pass in. But I would imagine you need to add that to the propTypes object before you use it.

Thank you so much as always.