We use yarn
to manage dependencies as it provides more reliable dependency list that the traditional npm.
Once you have yarn installed, you can run yarn install
.
With all dependencies installed, you can run npm run build
to build the project.
You can also use npm run watch
for continuous build.
Currently we use npm run watch
and python -m SimpleHTTPServer <port>
to serve the app.
In the future, we plan to migrate to use webpack-dev-server
with hot module loading support. (See #250 -- help wanted!)
-
Don't use
export default
(Why?). -
We make
index.ts
insideactions/
,models/
, andreducers/
export everything inside it so that we can just import fromactions
without worrying about file renaming later.
-
Action names should start with the part of the model it is modifying, so it's easy to categorize. For example, all bookmark actions have the "Bookmark" prefix.
-
Synchronous actions should implement
ReduxAction
interfaces insrc/actions/redux-action
, which follows pattern described in https://github.com/acdlite/redux-actions.-
Since we already have types, we do not make action creator functions.
-
For asynchronous actions, since they involve multiple sub-actions, we still have action creator functions (e.g.,
datasetLoad()
inactions/dataset.ts
). These action creators followredux-thunk
patterns.
-
-
In
src/action/index.ts
, we haveACTION_TYPE_INDEX
that uses TS's mapped type to declare so we make sure we generateACTION_TYPES
that contain all actions.
- In
src/models/shelf.ts
, we re-declare a number of Vega-Lite / CompassQL interfaces with "Shelf" prefix, allowing them to beSHORT_WILDCARD
or bothSHORT_WILDCARD
and fullWildcard
.
-
Since our props and states are immutable, we always use
PureComponent
for all of our components and rely on its shallow prop and state comparison. -
Use lowercase-dash-separated-names for file names. (Using PascalCase as filename can be problematic for OSX in general as OSX is case-insensitive.)
-
Following Redux's Using with React guide, we distinguish between presentation and container components. However, instead of having event handlers (e.g.,
onTodoClick
in the guide) for every single events, we pass inhandleAction
property to presentation components (which implements ourActionHandler
interface). For more information, seesrc/actions/redux-action.ts
. -
You can use this plugin to generate snippets (but manually remove default exports).
-
Use
render
as a prefix for class method that returns a React component and gets called by the component'srender
method (e.g.,renderAddFilterSpan
in<Field/>
). -
For CSS, we use react-css-modules and SASS, which makes it easy to modularize style in React using the
styleName
tag. (See react-css-modules's README for more details.)- Since CSS-Modules use filename as a prefix, never name a scss file
index.scss
. Instead use the module name. For example, the scss file fordata-pane/index.tsx
isdata-pane/data-pane.scss
.
- Since CSS-Modules use filename as a prefix, never name a scss file
-
We make our props and states immutable. (Using TypeScript's
Readonly
type wrapper in reducers is very helpful to enforce immutability.) -
We use
...
to make sure things are immutable and we don't cause side-effects. -
For array, we have utility methods in
src/reducers/util.ts
.
src/models
contains all interfaces and helper methods for our redux state.