Building React Applications with Umi, Dva, and Antd

Understanding the Three-Layer Architecture

React, a leading JavaScript framework, forms the foundation of modern web applications. In this project, we leverage additional tools to streamline development: Dva for state management, Antd for UI components, and Umi as a comprehensive framework solution.

Core Technologies

  • React: A JavaScript library for building user interfaces
  • Dva: A lightweight front-end framework based on Redux and React, providing simplified state management
  • Antd: An enterprise-class UI design language and React UI library
  • Umi: A comprehensive enterprise-level front-end application framework

Project Architecture

The application follows a three-layer architecture:

  1. Models: Handle application state and business logic
  2. Services: Manage API requests and data fetching
  3. Components: Present the UI and user interactions

Services Layer

The services layer contains functions that communicate with backend APIs. These functions typically return Promise objects and handle HTTP requests.

export function fetchData (requestData) {
    return request({
        method: "post",
        url: `${apiEndpoint}/data`,
        data: JSON.stringify(requestData),
    })
}

The underlying request function is a wrapper around axios:

import axios from "axios"

export default async function request (options) {
    let response
    try {
        response = await axios(options)
        return response
    } catch (err) {
        return response
    }
}

Models Layer

Models define the application state and how it can be modified. They contain namespace, state, reducers, effects, and subscriptions.

export default {
    namespace: "appData", // Namespace is required
    state: { count: 0 }, // Initial state values
    
    // Reducers handle state changes
    reducers: {
        incrementCount(state, { payload: { newCount }}) {
            return { ...state, count: newCount };
        },
    },
    
    // Effects handle asynchronous operations and business logic
    effects: {
        *fetchData({ payload: { id } }, { call, put, select }) {
            const { data } = yield call(apiService.fetchData, { itemId: id });
            
            yield put({
                type: "incrementCount",
                payload: {
                    newCount: data.value,
                },
            });
        },
        
        *loadUserInfo(_,{call,put}) {
            // Additional effect logic
        }
    },
    
    subscriptions: {
        // Listen to router changes and trigger actions
        setup ({ dispatch, history }) {
            return history.listen(({ pathname }) => {
                if (pathname==="/dashboard") {
                    dispatch({ type: "loadUserInfo" });
                }
            });
        }
    }
}

Components Layer

Components handle user interactions and dispatch actions to the models layer.

handleButtonClick = () => {
    dispatch({
        type: "appData/fetchData",
        payload: {
            id: this.state.currentId,
        },
    })
}

Data Flow Overview

The complete data flow follows this sequence:

  1. User interaction triggers a component handler
  2. The handler dispatches an action to the models layer
  3. The models layer effects process the action, potentially making API calls
  4. API responses trigger reducer actions to update state
  5. State changes trigger component re-rendering

Component State Connection

To connect components with the models state, use the connect function from dva:

import { Component } from "react"
import { connect } from "dva"

class Dashboard extends Component {
    handleButtonClick = () => {
        // Component implementation
    }
    
    render () {
        const { count } = this.props;
        
        return (
        <div>
            <button onClick={this.handleButtonClick}>Fetch Data</button>
            <p>Current count: {count}</p>
        </div>
    )
    }
}

function mapStateToProps (state) {
    const { count } = state.appData;
    return {
        count,
    };
}

export default connect(mapStateToProps)(Dashboard)

Best Practices for Rendering

Components re-render when state or props change. To optimize performance:

  • Keep render methods lightweight, focusing on UI presentation
  • Avoid complex data processing in render methods
  • Handle data transformations in the models layer
  • Pass processed data rather than raw data to child components

Tags: React Dva Antd Umi Frontend Architecture

Posted on Thu, 13 Aug 2026 16:12:36 +0000 by banjax