我正在使用ReactJS + Redux,以及Express和Webpack。有一个内置的API,我希望能够从客户端进行REST调用- GET,POST,PUT,DELETE。
使用Redux架构的方式和正确方法是什么?就简化程序,动作创建者,存储和反应路线而言,任何有关流程的良好示例都将非常有帮助。
先感谢您!
最简单的方法是使用redux-thunkpackage进行操作。这个软件包是一个redux中间件,因此,首先,您应该将其连接到redux:
redux-thunk
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers/index'; const store = createStore( rootReducer, applyMiddleware(thunk) );
这使您可以将async动作与常规sync动作一起分派。让我们创建其中之一:
async
sync
// 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 }); } }); } }
我更喜欢在呈现和容器组件上分离React组件。本文完美地描述了这种方法。
接下来,我们应该创建TodosContainer组件,该组件将为演示Todos组件提供数据。在这里,我们正在使用react-redux库:
TodosContainer
Todos
react-redux
// 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);
另外,如果要显示加载程序/错误消息,则应创建todosReducer,将处理FETCH_TODOS_SUCCESS操作以及其他2个操作。
todosReducer
FETCH_TODOS_SUCCESS
// 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 });
对于其它操作喜欢CREATE,UPDATE,DELETE没有什么特别的,他们正在实施方式相同。
CREATE
UPDATE
DELETE