Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Bug fixes and features should always come with tests. If you want a visual representation of the test coverage of your code run yarn test:coverage.
Unit - test both frontend code in isolation
E2E - to test the full stack completely on critical flows
When selecting dom elements use data-testid
instead of using a class or id.
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.
This is an example of how we structure our unit tests.
This is an example of how we structure our hook tests
Few rules for creating maintainable components in react.
We are sticking with the times and using Function Components.
We have decided to only export our components using named exports. That way we don't start importing our components with different names.
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 be 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.
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 150 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.
Another common thing that makes components bloated is defining multiple functions/components in the same file. Here are a few reasons it is a good idea to separate your functions and components into their own files.
You can unit test separately from the rest of the code.
If anyone decides that they can reuse that code its a quick and easy move to a shared folder.
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.
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.
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.
React Hooks (useState, useReducer)
On dynamic pages the url is the source of truth use the router when needed.
We prefer to use local state initially for component level state management.
We want to lift state up the component tree as needed.
Use local context to avoid prop drilling. Put context as high in the component tree as needed.
Try not to default to always adding state to the redux store. Use redux only when sharing state across multiple places in the app. You can read more about the differences between context vs redux here.
We use createSlice
from Redux Toolkit to create the actions and reducers.
We use createAsyncThunk
for async calls.
Everything in redux should be serializable. If there is anything that is stored inside of redux that CANNOT be serialized, it should not live inside of redux (ie, BigNumber).
We use React Hook Form for form state management.
Note: If you have questions about any of these practices, please reach out to the core developement team.
We use Chakra Ui to create a consistent user interface. We should be using the theme all the time. There should not be very many situations where the theme can not be used and if it can't we may need to think about updating our theme.
In order to have consistent, easy to navigate react projects we follow a certain folder structure.
We want to be separating business logic, implementation logic and the view for better code organization, readability and easier testing. When doing this we want to make it as easy as possible for people to find the code for the current screen you are on so they know when they could reuse something that has already been created. So we separate our local hooks, helper functions and nested components.
If there are children that are dependencies of a function we should nest them. Create a folder as the name of the exported function and move all dependencies into that folder.
Three Layers Deep: We do not want to nest too deeply. A good rule of thumb is only nest three layers deep starting from one of our aliases.
In the above example you will see that the One component has a child component that is only rendered with in the One component. You can also see that the Two component has a child called Three that is only rendered inside of the Two so the Three is nested within the Two's component folder.
Having the components nested in this way allows us to easily move or delete code knowing that all of its dependencies are packaged together. For example...
If we decide that the Two component needs to be a globally shared component. We can easily move that component to the correct shared folder and we know that its child Three is going to go with it.
Similarly if we decided that the One component did not need a Two component anymore we could delete the Two component and we would not accidentally leave the Three component lying around, taking up space and not being used for anything.
We should always be writing our code so it is easy to be moved and shared. As a general rule of thumb is to build the components, hooks and helpers local to the code that is using it. Once it is needed in multiple locations pull it out into the proper shared folder.
We use aliasing for our file paths so that we can easily nest components and not have to worry about traversing our files with the correct ../../../
The aliases are implemented for any of the folders in the src
folder.
We want to use Component Driven User Interface strategies to make sure we are creating ui that is reusable and maintainable.