Search code examples
reactjsrefactoringdry

DRY with Props in React


We have a component. Let's call it <MyComponent>. It is being used in a dozen different files. We wanted to change the styling on this component. Fortunately, the component exposes a property stylingProps. So, we wrote the following in each of the dozen files:

public render() {
   const styles = {color: "purple", background: "gold"}
   return(
      <MyComponent
          otherPropsUniqueToEachfile={"somethingOrOther"}
          styles={styles}
      >
         "Some text"
      </MyComponent>
   )}

How should I refactor this so that I am not adding the constant styles with the exact same values in a dozen different files? What is "the React Way" to do so?


Solution

  • I like to create common components for the app, which use the library components under the hood. The rest of my app uses these common components without any knowledge of the external library component. Then, I can use my common component to create an interface that my app can use to control its appearance or behavior in different states.

    For example, let's pretend your <MyComponent> is a button coming from a component library. In this example, let's pretend your app has three button variants, that I'll call "primary", "secondary", and "default".

    The goal is that in your app, you could import your custom Button component, and use it like this:

    <Button variant="primary" arbitraryProp={data}>Button Text</Button>
    

    And the variant="primary" will color/style it a particular way.

    One way to build the Button component to handle this would be:

    import ComponentLibraryButton from "component-library";
    import React from "react";
    
    function Button({ variant, ...rest }) {
      const styles =
        variant === "primary"
          ? { color: "purple", background: "gold" }
          : variant === "secondary"
          ? { color: "green", background: "blue" }
          : { color: "black", background: "gray" };
    
      return <ComponentLibraryButton {...rest} styles={styles} />;
    }
    

    I like creating a layer like this that sits between component libraries and the rest of my app. It makes it easy to create custom control like this, but also to swap out a new component library down the road without having to change all of the files that use components.