Chuyển tới nội dung chính

Store

ZMP cung cấp thư viện quản lý state. Phục vụ một centralized Store cho tất cả components trong ứng dụng.

Bạn vẫn có thể sử dụng các thư viện quản lý state khác như Redux.

Tạo Store

Đầu tiên cần tạo store. Tạo file store.js:

// Đầu tiên cần import createStore từ zmp-framework core
import { createStore } from 'zmp-framework/core';

// tạo store
const store = createStore({
// bắt đầu với state (dữ liệu sẽ lưu trong store)
state: {
users: []
// ...
},

// actions sẽ thao tác với state và xử lý các bất đồng bộ
actions: {
// context object chứa state của store được truyền vào dưới dạng đối số
getUsers({ state }) {
// gọi api
fetch('some-url')
.then((res) => res.jsstate
.then((users) => {
// gán users trả về cho state
state.users = users;
});
}
// ...
},

// getters cho phép lấy giá trị của state
getters: {
// context object chứa state của store được truyền vào dưới dạng đối số
users({ state }) {
return state.users;
}
}
});

// export store
export default store;

Store Parameters

storeParameters object:

State

state Một object chứ state của ứng dụng.

Actions

actions sử dụng để cập nhật state, tác vụ bất đồng bộ, gọi actions khác. Action handlers cung cấp một context object với store state và phương thức dispatch để gọi actions khác. Có thể truy xuất context.store để truy xuất state hoặc gọi actions với context.dispatch.

Tham số thư hai cung cấp data.

Nên cập nhật state bằng cách gán giá trị mới. Ví dụ:

// sửa đổi trạng thái hiện tại - NOT REACTIVE
state.users.push(...users);

// gán giá trị mới - REACTIVE
state.users = [...state.users, ...users];

Getters

getters handlers dùng để lấy dữ liệu từ state trong store.Ví dụ lấy một list users đã đăng ký (registered: true):

const store = createStore({
state: {
users: [
{ id: 1, name: '...', registered: true },
{ id: 2, name: '...', registered: false }
]
},
getters: {
registeredUsers: ({ state }) => {
return state.users.filter((user) => user.registered);
}
}
});

Getter handlers cung cấp một context object với store state. Không thể gọi actions khác từ getters.

Sử dụng Store

Cách sử dụng store sau khi tạo

Đầu tiên truyển store vào App instance:

// import our store
import store from 'path/to/store.js';

const app = new ZMP({
// truyền store cho tham số khởi tạo ứng dụng
store,
...
})

Truy xuất Store & State

Có thể truy xuất vào store thông qua instance của store đã tạo:

import store from 'path/to/store.js';

console.log(store.state.users);

Hoặc từ ZMP instance' store property:

import { zmp } from "zmp-framework/react";

// ...
console.log(zmp.store.state.users);

Dispatching Actions

Để gọi một action cần gọi phương thức store.dispatch cùng tên của action.

Ví dụ có action getUsers:

const store = createStore({
// ...
actions: {
// nhận dữ liệu tuỳ chỉnh thông qua đối số thứ 2
getUsers({ state }, { total }) {
fetch(`some-url?total=${total}`)
.then((res) => res.json())
.then((users) => {
state.users = users;
});
}
}
// ...
});

Cần gọi phương thức store.dispatch:

import store from 'path/to/store.js';

// gọi 'getUsers' actions
store.dispatch('getUsers', { total: 10 });

Nếu muốn gọi action khác từ action handler:

const store = createStore({
// ...
actions: {
setLoading({ state }, isLoading) {
state.isLoading = isLoading;
},
// context object còn chứa phương thức "dispatch"
getUsers({ state, dispatch }, { total }) {
// gọi một action khác
dispatch('setLoading', true);
fetch(`some-url?total=${total}`)
.then((res) => res.json())
.then((users) => {
state.users = users;
// gọi action khác
dispatch('setLoading', false);
});
}
}
// ...
});

Getters

tạo các getters bằng cách định nghĩa tại store.getters.

const store = createStore({
state: {
count: 10
},
getters: {
count({ state }) {
return state.count;
},
double({ state }) {
return state.count * 2;
}
}
});
import store from 'path/to/store.js';

const count = store.getters.count;
const double = store.getters.double;

Getter value là một object với property .value cung cấp giá trị mà getter trả về, so:

console.log(count.value); // -> 10
console.log(double.value); // -> 20

Sử dụng với React Components

zmp-react cung cấp useStore helper để sử dụng trong React components (tự động cập nhật components khi state/getters values thay đổi).

*useStore(getterName)- trả về getter value và theo dõi sự thay đổi của state*

  • getterName - string - tên của getters handler

phương thức trả về getter value

Nếu muốn lấy getter value từ store instance khác:

*useStore(store, getterName)- trả về getter value và theo dõi sự thay đổi của state*

  • store - store instance - Nếu bỏ trống mặc định sẽ là store của ứng dụng đã được truyề n vào <App/>.
  • getterName - string - tên của getters handler

phương thức trả về getter value

Ví dụ:

const store = createStore({
state: {
users: []
},
actions: {
getUsers({ state }) {
// ...
}
},
getters: {
users({ state }) {
return state.users;
}
}
});

React component:

import React, { useEffect } from 'react';
// import useStore hook
import { useStore, Page, List, ListItem } from 'zmp-framework/react';
// import store
import store from 'path/to/store.js';

export const UsersPage = () => {
// lấy "users" trong store
const users = useStore('users');

useEffect(() => {
// gọi action getUsers
store.dispatch('getUsers');
}, []);

return (
<Page>
<List>
{users.map((user, index) => (
<ListItem title={user.name} key={index} />
))}
</List>
</Page>
);
};

bởi vì sử dụng useStore helper/hook, component tự động cập nhật khi users tải xong.

Ví dụ

import { createStore } from 'zmp-framework/core';

const store = createStore({
state: {
loading: false,
users: []
},
actions: {
getUsers({ state }) {
state.loading = true;
setTimeout(() => {
state.users = ['User 1', 'User 2', 'User 3', 'User 4', 'User 5'];
state.loading = false;
}, 3000);
}
},
getters: {
loading({ state }) {
return state.loading;
},
users({ state }) {
return state.users;
}
}
});

export default store;
import React from 'react';
import {
useStore,
Page,
Navbar,
Card,
List,
ListItem,
Button
} from "zmp-framework/react";
import store from './store';

export default () => {
const loading = useStore('loading');
const users = useStore('users');
const loadUsers = () => {
store.dispatch('getUsers');
};

return (
<Page>
<Navbar backLink title='Store' />
{users.length && (
<List>
{users.map((user) => (
<ListItem title={user} key={user} />
))}
</List>
)}
{!users.length && (
<Card inset>
<Button fill preloader loading={loading} onClick={loadUsers}>
Load Users
</Button>
</Card>
)}
</Page>
);
};