For any development on Re:Earth's front-end, please follow the guidelines that follow. Our goal with this guide is to keep the source code as readable and clear as possible, as well as allow for new developers (both core and community) to be able to create high-quality PRs without too much headache.
Note: Due to having eslint setup to catch quite a few syntax and code layout issues out of the box, we have not included those here. Please make sure your IDE is setup properly.
useMemo
- Use to avoid unnecessary re-processing and re-rendering of processed objects or variables, but only use it when computational cost is high (think
O(n)
or greater in cost). - Use to avoid unnecessary re-rendering of props and status values wrapped in objects or arrays.
Bad | Good |
---|---|
const item = data?.find(d => d.id === id);
const object = { id }; |
const item = useMemo(() => {
return data?.find(d => d.id === id);
}, [data, id]);
const object = useMemo(() => { id }, [id]); |
useCallback
Use for MOST functions within a React component to better handle renders based on dependencies. Even if no dependencies, a useCallback will make sure React knows the function will always be the same, so don’t need to re-render
Query and mutation exports should live inside the src/gql/queries
directory only. Contents of each file should be queries, followed by mutations.
Naming of variables in TypeScript codes should be in upper SNAKE_CASE. Naming of queries and mutations should be in PascalCase.
Query names should be in the GetXxxx
format. Mutation names and variables should generally mirror the backend, but in PascalCase and SNAKE_CASE, respectively.
Bad | Good |
---|---|
export const Import_Dataset = gql`
mutation importAllDataset($file: Upload!, $sceneId: ID!, $datasetSchemaId: ID) {
importDataset(input: { file: $file, sceneId: $sceneId, datasetSchemaId: $datasetSchemaId }) {
datasetSchema {
id
name
}
}
}
`; |
export const IMPORT_DATASET = gql`
mutation ImportDataset($file: Upload!, $sceneId: ID!, $datasetSchemaId: ID) {
importDataset(input: { file: $file, sceneId: $sceneId, datasetSchemaId: $datasetSchemaId }) {
datasetSchema {
id
name
}
}
}
`; |
Naming
We have two styles when naming functions: onXXXX
and handleXXXX
. Note both are camelCase. We use onXXXX
for functional props, and we use handleXXXX
when we are locally declaring the function.
Word order
Should be nounVerb
. Combining this with deliberate prop or export order keeps things very easy to read.
Bad | Good |
---|---|
onRemoveAsset
onHandleAddDataset
OnUpdatetheme
handleSyncDataset
updateProject
fetchuser |
onAssetAdd
onAssetRemove
onAssetUpdate
handleProjectAdd
handleProjectRemove
handleProjectUpdate |
Naming
Descriptive over short. Context matters, of course, so generic code can and should have name
instead of teamName
. But typically teamName
is preferable over name
.
Follow Clean Code unless absolutely necessary. Which, in a nutshell, is "If you need a comment, either your function or variable isn't named appropriately, or your function is doing too much and should be broken down into simpler functions".
Re:Earth is broken up into 4 component categories: Pages
, Organisms
, Molecules
and Atoms
. See the component directory's README for details specific to Re:Earth.
Unless heavily nested and used only in its own or its parent directory, start from the @reearth/
alias for the src directory.
Bad | Good |
---|---|
import CoolComponent from "../../../../CoolComponent; |
import CoolComponent from "@reearth/components/atoms/CoolComponent; |
NOTE: Often ESlint will catch spacing issues on save, but not always. Because of this, be mindful of your spacing as it affects the file's readability immensely. For order, ESlint will only fix import order.
Since file content varies in size, complexity, whether it is a component or utility, hooks, etc., it is hard to set specific rules for spacing and order. We only ask that you be deliberate (and take time refactoring before opening a PR) and be open to suggestions on spacing or order during PR review to keep code as readable and accessible to new eyes as possible.
When possible use spread and rest syntax. If props, write ...props
, not ...rest
or another word.
Abbreviations, like CSV, JSON or HTML, should always be uppercase OR lowercase.
Bad | Good |
---|---|
const parseCsv = () => {} |
const parseCSV = () => {} |
When adding, be deliberate on whether a dependency is a dev dependency or not. Also, don't forget to use the -E
parameter so that the exact same version is used in all environments. This is especially important for local development.
Cheat table
Action | Syntax |
---|---|
Add new |
yarn add <package...> -E |
Mass upgrades |
yarn upgrade-interactive --latest |