This is my attempt to build a simple Todo app with umi, dva.
A sequence of steps that I did to create this Todo app.
- Read [umi Getting Started guide]
yarn global add umi
- Create a new project directory:
mkdir todo-umi-dva
- Bootstrap
umi
:yarn create umi
- For boilerplate type: choose app
- For use typescript: enter y
- For functionality do you want to enable, select everything(antd, dva, code splitting, dll, internationalization)
- Install dependencies:
yarn install
- Run in dev mode:
umi dev
- Visit via the browser:
http://localhost:8000
- Edit
src/layouts/index.css
- Import antd's CSS:
@import '~antd/dist/antd.css';
(From Ant Design's Use in Typescript) - Delete
font-family
related lines to use Ant Design's default.
- Import antd's CSS:
- Edit
src/layouts/index.tsx
- Import Ant components
import { Layout, Menu, Breadcrumb } from 'antd'; const { Header, Content, Footer } = Layout;
- Update
render()
to return Ant layout. Noticeprops.children
is rendered within theContent
block.
- Import Ant components
- Create Todo directory:
mkdir -p src/pages/todo
- Create a file to declare domain types:
touch src/pages/todo/types.ts
- Create a
Todo
class. We'll come back to the Model file to wire updva
- Create a
- Create a Mock file to host the mock service:
touch src/pages/todo/_mock.ts
- Mock
/api/todos
service (see source) - Try it out:
- Post new Todo:
curl -XPOST -H"Content-Type: application/json" -d'{"description" : "hello"}' localhost:8000/api/todos
- Get Todos:
curl localhost:8000/api/todos
- Patch Todo:
curl -XPATCH -H"Content-Type: application/json" -d'{"completed": true}' localhost:8000/api/todos/0
- Post new Todo:
- Mock
- Create a Service file:
touch src/pages/todo/service.ts
- Create
TodoService
, see source
- Create
- Create an
index.tsx
file:touch src/pages/todo/index.tsx
- Put in the basic frontend code:
- Refresh the page to see it:
http://localhost:8080/todo
This is perhaps the most complicated thing... :/
- Create
src/pages/todo/model.ts
- Set namespace to
todos
- Create
TodoState
- Initialize state as a type of
TodoState
- Add a reducer
- Add effects. Each "effect" is later triggered by
dispatch
astype: "[namespace]/[effect name]"
, withpayload
- Once an effect is completed, use
yield put
to trigger a reducer
- Set namespace to
- In
src/pages/todo/index.tsx
- Declare an Props interface to access
dispatch
,loading
, and data fromdva
interface ViewProps extends TodoState { dispatch: any; loading: boolean; }
- Use decoration to connect
dva
to component.@connect(({ todos, loading }) => ({ todos, loading: loading.models.todos, }))
- What does
@connect
do? See this blog, and Proper Typing of react-redux Connected Components - Where does
loading
coming from? See dva#1464
- Declare an Props interface to access
- In
src/layouts/index.tsx
- Each
<Menu>
uses the path askey
, e.g.,<Menu.Item key="/">Home</Menu.Item>
- Use
<Link>
to navigate to URL, e.g.,<Link to="/">Home</Link>
- In
<Menu>
, uselocation.pathname
to select current item:<Menu ... defaultSelectedKeys={[location.pathname]}>...</Menu>
- Each
- Read UmiJS - Router - Extending Routing by Annotation
- Page title can be set in the comment
/** * title: Page Title */
- Read umi-lint instructions
- Add lint:
yarn add umi-lint --dev
- Add to
package.json
"scripts": { ... "lint:umi": "umi-lint --tslint --prettier src/", "precommit:umi": "umi-lint --staged --tslint --stylelint --prettier --fix" ... }
- Run:
yarn lint:umi