loading...

What makes you think "Ok, that should be a component"?

vtrpldn profile image Vitor Paladini ・1 min read

Whenever we are building web apps, SPAs and whatnot we have the option to turn the just written piece of code in a component.

Considering the pros and cons of doing so, when exactly do you create a component and what rules do you follow?

Discussion

markdown guide
 

I agree with most things that Dan said in that talk but I lean more to how Kent C Dodds approaches this issue. They kinda say the same thing but I feel that Kent's point encourages you to think more about the way you abstract things instead of setting a hard rule like DRY or WET.

kentcdodds.com/blog/aha-programming/

 

I usually create components when at least one of the following apply:

  1. I'm implementing a component already described in a style guide
  2. The particular piece of code is complex and might make the current page/section code needlessly confusing
  3. I've already implemented similar logic before, so I wrap both implementations in a single component IF doing so makes the code easier to understand
 

Usually it's the "third" time I write the same stuff, then I will consider making it a component. But it also depends, for instance for a button I just put a .button class to every button, even it got repeated everywhere I don't write it as component if the function is simple.

 

I like to split up my components 1:1 with UI elements. Then I'll split beyond that if styles get too big. I call it a more relaxed take on smart and dumb components.

 

That's interesting, can you share a code example?

 

Sure thing. Here is a chat room

chat-room

This is the top level component

const ChatRoom = e(x => {
  useEffect(() => {
    pipe([
      APIClient.findRooms,
      fork([
        x.setRooms,
        pipe([
          get([0, 'id']),
          x.setCurrentRoom,
        ]),
      ]),
    ])()
  }, [])
  return Div({
    style: {
      display: 'grid',
      gridTemplateColumns: '20% auto',
      width: '100%',
    },
  }, [
    ChatRoomSideBar(x),
    Div({
      style: {
        display: 'flex',
        justifyContent: 'center',
      },
    }, [Div({
      style: {
        width: '100%',
      },
    }, [
      ChatRoomDetail(x),
      ChatRoomChat(x),
    ])]),
  ])
})
  • ChatRoomSideBar - sidebar on the left
  • ChatRoomDetail - the top right box with chat room name and users
  • ChatRoomChat - the bottom right chat list with input to send chat

I say it's a more relaxed version of smart and dumb components because ChatRoomChat is a smart component inside another smart component ChatRoom and manages its own high level state with useReducer. The way everything gets laid out ends up becoming somewhat arbitrary in terms of smart and dumb. The real goal is to bring effects and state to where they absolutely need to be. ChatRoomSideBar and ChatRoomDetail are dumb, they only hold elements and styles.

Very interesting, thanks for sharing!

 

If you have to write it twice extract it into component.

This works most for us since we already have lots of style components (polaris)

 

I see. I also follow that rule sometimes but I'm actually pretty comfortable duplicating code if the right abstraction is still not clear to me. I'd much rather have simple, easy to understand duplicated code than an over-engineered component for instance.

 

Yeah, it makes sense. Duplication is better than sloppy abstraction