---
# System prepended metadata

title: V3 Component layout & structure
tags: [' magesmiths', v3]

---

---
tags: v3, magesmiths
---
# V3 Component layout & structure

Things to keep in mind when developing components in React wiht TypeScript.

## Function Components

It is current year afterall and we're sticking witht the times by using Function Components.

## Imports
We want consistency in our components and that starts with imports. 

```
- React imports
- Third party package imports
(space)
- react contexts
- react components (includes layouts/pages)
- js services
- js utilities
- Styles (styled components)
- Types/Interfaces
(space)
- React.lazy dynamic imports
```

Example:
```jsx
import React, { useEffect, useState, lazy, Suspense } from "react";
import { Switch, Route, useParams } from "react-router-dom";
import { CheckboxProps } from '@radix-ui/react-checkbox';
import { RiCheckLine, RiAsterisk } from 'react-icons/ri';

import { useDao } from "../contexts/DaoContext";
import Dao from "../pages/Dao";
import Layout from "../components/Layout";
import { MolochService } from "../services/MolochService";
import { convertTimeUnits } from "../utils/Time";
import {
  StyledDiv,
  StyledContainer,
  StyledElement
} from "./MyAwesomeComponent.styles";
import { SharedType, SharedInterface } from "../types/shared-types"

const HeavySubPage = lazy(() => import("../pages/HeavySubPage"));
```

## Component Body

```
- Type definition (Unless imported)
- Function declaration w/ props
- destructure contexts
- destructure props
(space)
- useState
- useRef
- simple expressions
(space)
- useEffect/useMemo
(space)
- Functions/useCallback
(space)
- Return statement (TSX)
```

Example:

```jsx
/// TYPE DEFINITION
type MyAwesomePropsType = {
  bigProps: {
      smallProp: SmallPropsType, 
      anotherSmallProps: AnotherSmallPropsType
  }
  className?: string;
  onClick?: React.MouseEventHandler<HTMLButtonElement>;
};

/// FUNCTION DECLARATION
export const MyAwesomeComponent: React.FC<MyAwesomeProps> = ({ bigProps }) => {
  //  DEPENDENCY DECLARATIONS
  const { address, injectedProvider } = useInjectedProvider();
  const { errorToast } = useOverlayContext();
  //  Don't have to destructure props, just an example of placement
  const { smallProp, anotherSmallProps } = bigProps;

  /// STATE DECLARATIONS
  const [state, setState] = useState(null);
  const [loading, setLoading] = useState(false);
  const ref = useRef(null);
  const isTrue = smallProp ? "yes" : "no";

  //  SIDE EFFECTS
  useEffect(() => {
    const painInTheAssAsyncFn = async (address) => {
      setLoading(true);
      try {
        const sumthin = await fetchSumthin(address);
        setState(sumthin);
      } catch (error) {
        console.error(error);
        errorToast({
          title: "Didn't Work",
          description: "It didn't work, ok?",
        });
        setState(null);
      } finally {
        setLoading(false);
      }
    };
    if (!state && address) {
      painInTheAssAsyncFn(address);
    }
  }, [state, address]);
};

//  FUNCTIONS
const handleClick = () => {
  setState(false);
};

//  OUTPUT
return (
  <div>
    <h1>Hey!</h1>
    <button onClick={handleClick}>Click this!</button>
  </div>
);
```

### Named exports only

We have decided to only export our components using named exports. That way we don't start importing our components with different names.

```jsx
// Bad
export default MyAwesomeComponent = () => ({})
import MyAwesomeComponent from 'MyAwesomeComponent'

// Good
export const MyAwesomeComponent = () => ({})
import { MyAwesomeComponent } from 'MyAwesomeComponent'
```


### Small component files

We should really be striving to have small component files. When files get large and bloated they become harder to maintain, there are more merge conflicts, and they are harder to test.

Our goal as React developers should be to make our code as reusable as possible. Bloated components never end up being reusable and the reusability potential becomes harder to see because the component is so complex. Here are a few things to help create smaller components.

### File Size

There is no magic number to say how many lines is too much. But if we are writing code and it starts to approach or pass the 200-300 line mark, we should start asking our selves if it can be broken down into smaller more digestible chunks and/or needs to use some already created shared code to help slim it down.

### Try to only define one component/function per file

Another common thing that makes components bloated is defining multiple functions/components in the same file. Here are a few reasons why it is a good idea to separate your functions and components into their own files.

1. You can unit test separately from the rest of the code.
2. If anyone decides that they can reuse that code its a quick and easy move to a shared folder.
3. It can be confusing when you are looking for a component that is exported from a file that does not share the same name. It sounds trivial but it removes just a little bit of friction.

### Use your judgement when splitting out components

You don't need to split out components just to split them out. If you define a component to use within the root component and it is a small couple line component maybe it does not need to be pulled out. But if you start getting components that is large and takes a hand full of props maybe it should be pulled out into it's own file.

### Views should be dumb

Separate the business logic from the view as much as possible. Create hooks, helpers & reducers to utilize this logic from the UI and test that code in isolation from it's UI.