Cách đơn giản nhất, là sử dụng gói redux-thunk
. Gói này là một middleware Redux, vì vậy trước hết, bạn nên kết nối nó với Redux:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
này cho phép bạn để gửi async
hành động cùng với thường xuyên sync
hành động. Hãy tạo một trong số chúng:
// actions.js
export function fetchTodos() {
// Instead of plain objects, we are returning function.
return function(dispatch) {
// Dispatching REQUEST action, which tells our app, that we are started requesting todos.
dispatch({
type: 'FETCH_TODOS_REQUEST'
});
return fetch('/api/todos')
// Here, we are getting json body(in our case it will contain `todos` or `error` prop, depending on request was failed or not) from server response
// And providing `response` and `body` variables to the next chain.
.then(response => response.json().then(body => ({ response, body })))
.then(({ response, body }) => {
if (!response.ok) {
// If request was failed, dispatching FAILURE action.
dispatch({
type: 'FETCH_TODOS_FAILURE',
error: body.error
});
} else {
// When everything is ok, dispatching SUCCESS action.
dispatch({
type: 'FETCH_TODOS_SUCCESS',
todos: body.todos
});
}
});
}
}
Tôi thích tách riêng các thành phần phản ứng trên các thành phần hiện tại và thùng chứa. Cách tiếp cận này được mô tả một cách hoàn hảo trong this article.
Tiếp theo, chúng ta nên tạo thành phần TodosContainer
, sẽ cung cấp dữ liệu cho thành phần Todos
hiện tại. Ở đây, chúng ta đang sử dụng react-redux
thư viện:
// TodosContainer.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchTodos } from '../actions';
class TodosContainer extends Component {
componentDidMount() {
// When container was mounted, we need to start fetching todos.
this.props.fetchTodos();
}
render() {
// In some simple cases, it is not necessary to create separate `Todos` component. You can put todos markup directly here.
return <Todos items={this.props.todos} />
}
}
// This function is used to convert redux global state to desired props.
function mapStateToProps(state) {
// `state` variable contains whole redux state.
return {
// I assume, you have `todos` state variable.
// Todos will be available in container component as `this.props.todos`
todos: state.todos
};
}
// This function is used to provide callbacks to container component.
function mapDispatchToProps(dispatch) {
return {
// This function will be available in component as `this.props.fetchTodos`
fetchTodos: function() {
dispatch(fetchTodos());
}
};
}
// We are using `connect` function to wrap our component with special component, which will provide to container all needed data.
export default connect(mapStateToProps, mapDispatchToProps)(TodosContainer);
Ngoài ra, bạn nên tạo todosReducer
, mà sẽ xử lý FETCH_TODOS_SUCCESS
hành động, và 2 hành động khác nếu bạn muốn hiển thị tin nhắn nạp/lỗi.
// reducers.js
import { combineReducers } from 'redux';
const INITIAL_STATE = {
items: [],
isFetching: false,
error: undefined
};
function todosReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case 'FETCH_TODOS_REQUEST':
// This time, you may want to display loader in the UI.
return Object.assign({}, state, {
isFetching: true
});
case 'FETCH_TODOS_SUCCESS':
// Adding derived todos to state
return Object.assign({}, state, {
isFetching: false,
todos: action.todos
});
case 'FETCH_TODOS_FAILURE':
// Providing error message to state, to be able display it in UI.
return Object.assign({}, state, {
isFetching: false,
error: action.error
});
default:
return state;
}
}
export default combineReducers({
todos: todosReducer
});
Đối với các hoạt động khác như CREATE
, UPDATE
, DELETE
không có gì đặc biệt, họ đang thực hiện theo cùng một cách là.
cảm ơn bạn rất nhiều vì đã giúp đỡ. vẫn cố gắng nắm bắt khái niệm. bạn gọi hành động từ một thành phần như thế nào và ở đâu? bạn cũng có thể làm rõ thêm một chút về '.then (response => response.json(). sau đó (body => ({response, body}))) .then (({response, body}) => { 'đang làm gì? Cảm ơn một lần nữa –
@ JoKo, vâng, tôi sẽ cập nhật câu trả lời sớm. – 1ven
@ JoKo, câu trả lời cập nhật – 1ven