Understanding Dva: A Lightweight Frontend Framework Based on Redux and Redux‑Saga
This article explains what Dva is, the problems it solves, its advantages and disadvantages, core concepts, minimal application structure with code examples, and the underlying implementation details, comparing it with React, React‑Redux, and Redux‑Saga, helping developers understand its role in frontend development.
Dva is a lightweight application framework built on top of Redux and redux‑saga, additionally bundling react‑router and fetch to simplify development experience.
Problems Dva Solves
Traditional Redux projects suffer from file switching overhead, difficulty organizing business models, cumbersome saga creation, and complex entry setup involving store creation, middleware configuration, router initialization, Provider binding, saga initialization, and HMR handling.
Advantages of Dva
Easy to learn and use with only six APIs, especially friendly to Redux users; when used with Umi, it can be reduced to zero APIs.
Elm‑inspired model concept using reducers, effects, and subscriptions to organize state.
Plugin mechanism (e.g., dva-loading ) automatically handles loading states.
Supports HMR via babel-plugin-dva-hmr .
Disadvantages of Dva
Future uncertainty: after the Dva@3 plan was announced, the official team has largely stopped maintenance.
For many simple scenarios, Hooks can replace Dva.
Applicable Scenarios
Business scenarios with complex component communication requiring state management.
Technical scenarios using React class components.
Core Concepts
Dva follows the Redux data flow: actions are dispatched, synchronous actions go directly to reducers to update state, while asynchronous actions trigger effects (sagas) before reaching reducers.
Key Redux concepts include State (immutable JavaScript object), Action (plain object), dispatch (function to trigger actions), Reducer (pure function to compute new state), Effects (side‑effects handled by redux‑saga using generators), and Connect (function to bind state to view).
Additional concepts: Subscriptions (collect actions from sources like keyboard, websocket, etc.), Router (uses react‑router), and Route Components (presentational components separate from model‑connected components).
Minimal Dva Application Structure
Without Model
import dva from 'dva';
const App = () =>
Hello dva
;
const app = dva();
app.router(() =>
);
app.start('#root');With Model
const app = dva();
app.use(createLoading());
app.model({
namespace: 'count',
state: 0,
reducers: {
add(state) { return state + 1; }
},
effects: {
*addAfter1Second(action, { call, put }) {
yield call(delay, 1000);
yield put({ type: 'add' });
}
}
});
app.router(() =>
);
app.start('#root');Underlying Implementation
Dva consists of two packages: dva (high‑order component layer using react‑redux) and dva-core (model layer using redux‑saga).
The dva function creates an app object, proxies router and start , and connects the view layer. It sets up history, middleware, and renders the React tree.
export default function (opts = {}) {
const history = opts.history || createHashHistory();
const createOpts = { /* ... */ };
const app = create(opts, createOpts);
const oldAppStart = app.start;
app.router = router;
app.start = start;
return app;
function router(router) { /* ... */ }
function start(container) { /* ... */ }
}The dva-core create function builds the app instance, exposing use , model , and start . The start method initializes the Redux store, registers reducers and sagas, runs subscriptions, and provides model management APIs.
export function create(hooksAndOpts = {}, createOpts = {}) {
const { initialReducer, setupApp = noop } = createOpts;
const plugin = new Plugin();
plugin.use(filterHooks(hooksAndOpts));
const app = { _models: [prefixNamespace({ ...dvaModel })], _store: null, _plugin: plugin, use: plugin.use.bind(plugin), model, start };
return app;
}
function start() { /* store init, saga run, subscriptions */ }Comparison with React, React‑Redux, and Redux‑Saga
React alone requires lifting state to common ancestors. React‑Redux extracts state into a store, connects components via connect , and enables middleware interception. Redux‑Saga handles asynchronous side‑effects as middleware. Dva unifies store, saga, and model concepts, adds subscriptions, and offers a concise DSL‑like API.
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.