环境搭建
以spring-boot react redux增删改查为基础代码,在redux
分支的基础上,集成redux-thunk
中间件,实现增删改查
- 检出代码
git clone https://gitee.com/qinaichen/react-crud.git
cd react-crud
- 切换分支
git checkout redux
- 创建新分支
git checkout -b redux-thunk
- 添加
redux-thunk
cd web
npm install redux-thunk --save
- 将
redux-thunk
添加到store
中
redux
中想要使用中间件,就要使用applyMiddleware
import { createStore,applyMiddleware } from 'redux'
- 引入
redux-thunk
import thunk from 'redux-thunk'
- 同时使用
redux-thunk
和redux-devtools-extension
import { createStore,applyMiddleware , compose} from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
const componseEnhancers = window.__REDUX_DEVTOOLS_EXTESION_COMPOSE__ || compose;
const enhancer = componseEnhancers(
applyMiddleware(thunk)
);
const store = createStore(reducer,enhancer);
export default store;
到这里,我们就完全搭建好了redux-thunk
的使用环境,但是我们还不能立刻使用其来完成我们的功能,首先要做的就是要将reducer
中的action
和action type
抽取出来
抽取actionType
- 在
store
目录先创建actionTypes.js
export const CHANGE_USER_NAME = 'change_user_name';
export const INIT_USER_LIST = 'init_user_list';
export const EDIT_USER_NAME = 'edit_user_name'
export const SET_USER_EMPTY = 'set_user_empty';
- 替换
reducer
中的内容
import { CHANGE_USER_NAME,INIT_USER_LIST,EDIT_USER_NAME,SET_USER_EMPTY} from './actionTypes'
const defaultState = {
id:'',
name:'',
list:[]
}
export default (state = defaultState,action)=>{
/**
* 表单控件修改逻辑
*/
if(action.type === CHANGE_USER_NAME){
const newState = Object.create(state);
newState.name = action.name;
return newState;
}
/**
* 初始化list
*/
if(action.type === INIT_USER_LIST){
const newState = Object.create(state);
newState.list = action.list;
return newState;
}
/**
* 编辑用户
*/
if(action.type === EDIT_USER_NAME){
const newState = Object.create(state);
const {id,name} = action.user;
newState.id = id;
newState.name = name;
return newState;
}
/**
* 将state中的id和name设置为空
*/
if(action.type === SET_USER_EMPTY){
const newState = Object.create(state);
const {id,name} = action.user;
newState.id = id;
newState.name = name;
return newState;
}
return state;
}
- 替换
App.js
中的内容
import React, {Component} from 'react';
import axios from 'axios'
import './App.css'
import Table from './Table'
import Form from './Form'
import store from './store'
import { CHANGE_USER_NAME,INIT_USER_LIST,EDIT_USER_NAME,SET_USER_EMPTY} from './store/actionTypes'
class App extends Component {
constructor(props) {
super(props);
this.state = store.getState();
store.subscribe(()=>{
this.setState(store.getState());
})
}
render() {
return (
<div className="container-fluid" style={{marginTop: '20px'}}>
<div className="row">
<div className="col-xs-4 col-xs-offset-1">
<Table list={this.state.list} edit={this.edit} deleteItem={this.deleteItem}></Table>
</div>
<div className="col-xs-3 col-xs-offset-1">
<Form name={this.state.name} handleChange={this.handleChange} submit={this.handleFormSubmit}></Form>
</div>
</div>
</div>
);
}
componentDidMount(){
this.query();
}
edit = (item) => {
const action = {
type:EDIT_USER_NAME,
user:item
}
store.dispatch(action)
}
query = () => {
axios.get('/user').then(({data})=>{
const action = {
type:INIT_USER_LIST,
list:data
};
store.dispatch(action);
})
}
deleteItem = (item) => {
axios.delete(`/user/${item.id}`).then(({data})=>{
this.query();
})
}
handleChange = (name) =>{
const action = {
type: CHANGE_USER_NAME,
name
};
store.dispatch(action);
}
handleFormSubmit = (e) => {
e.preventDefault();
if(this.state.name !== ''){
axios.post('/user',{
id:!this.state.id?'':this.state.id,
name:this.state.name
}).then(({data})=>{
const action = {
type:SET_USER_EMPTY,
user:{id:'',name:''}
}
store.dispatch(action);
this.query();
})
}
}
}
export default App;
创建actionCreator
- 在
store
目录下创建actionCreator.js
import { CHANGE_USER_NAME,EDIT_USER_NAME,SET_USER_EMPTY ,INIT_USER_LIST} from './actionTypes'
/**
* 更新用户名称
* @param name
* @returns {{type: string, name: *}}
*/
export const changeUsernameAction = (name) =>({
type: CHANGE_USER_NAME,
name
})
/**
* 修改用户信息
* @param user
* @returns {{type: string, user: *}}
*/
export const editUserAction = (user)=>({
type:EDIT_USER_NAME,
user
})
/**
* 用户信息置空
* @returns {{type: string, user: {id: string, name: string}}}
*/
export const setUserEmptyAction = () =>({
type: SET_USER_EMPTY,
user:{id:'',name:''}
})
/**
* 初始化用户信息列表
* @param list
* @returns {{type: string, list: *}}
*/
export const initUserListAction = (list) =>({
type:INIT_USER_LIST,
list
})
- 在
App.js
中引入actionCreator
import React, {Component} from 'react';
import axios from 'axios'
import './App.css'
import Table from './Table'
import Form from './Form'
import store from './store'
import {editUserAction,initUserListAction,changeUsernameAction,setUserEmptyAction} from './store/actionCreator'
class App extends Component {
constructor(props) {
super(props);
this.state = store.getState();
store.subscribe(()=>{
this.setState(store.getState());
})
}
render() {
return (
<div className="container-fluid" style={{marginTop: '20px'}}>
<div className="row">
<div className="col-xs-4 col-xs-offset-1">
<Table list={this.state.list} edit={this.edit} deleteItem={this.deleteItem}></Table>
</div>
<div className="col-xs-3 col-xs-offset-1">
<Form name={this.state.name} handleChange={this.handleChange} submit={this.handleFormSubmit}></Form>
</div>
</div>
</div>
);
}
componentDidMount(){
this.query();
}
edit = (item) => {
store.dispatch(editUserAction(item))
}
query = () => {
axios.get('/user').then(({data})=>{
store.dispatch(initUserListAction(data));
})
}
deleteItem = (item) => {
axios.delete(`/user/${item.id}`).then(({data})=>{
this.query();
})
}
handleChange = (name) =>{
store.dispatch(changeUsernameAction(name));
}
handleFormSubmit = (e) => {
e.preventDefault();
if(this.state.name !== ''){
axios.post('/user',{
id:!this.state.id?'':this.state.id,
name:this.state.name
}).then(({data})=>{
store.dispatch(setUserEmptyAction());
this.query();
})
}
}
}
export default App;
将异步逻辑迁入actionCreator
在没有使用redux-thunk
时,在actionCreator
中定义的每一个action
函数,只能返回一个对象,而使用了redux-thunk
中间件,就可以让action
函数返回一个函数,返回的这个函数就能执行异步操作,所以在App.js
中的查询和删除逻辑,都可以放到actionCreator
中进行操作
- 在
actionCreator
中定义异步操作函数
import axios from 'axios'
/**
* 从服务器加载用户列表
* @returns {Function}
*/
export const getAllUser = () =>{
return (dispatch)=>{
axios.get('/user').then(({data})=>{
const action = initUserListAction(data);
dispatch(action);
})
}
}
/**
* 保存用户信息
* @param user
* @returns {Function}
*/
export const saveUser = (user) =>{
return (dispatch)=>{
axios.post('/user',user).then(({data})=>{
dispatch(setUserEmptyAction());
dispatch(getAllUser());
})
}
}
/**
* 删除用户
* @param id
* @returns {Function}
*/
export const deleteUser = (id) =>{
return (dispatch)=>{
axios.delete(`/user/${id}`).then(({data})=>{
dispatch(getAllUser());
})
}
}
- 将异步逻辑引入
App.js
import React, {Component} from 'react';
import './App.css'
import Table from './Table'
import Form from './Form'
import store from './store'
import { changeUsernameAction,
editUserAction,
getAllUser,
saveUser,
deleteUser
} from './store/actionCreator'
class App extends Component {
constructor(props) {
super(props);
this.state = store.getState();
store.subscribe(()=>{
this.setState(store.getState());
})
}
render() {
return (
<div className="container-fluid" style={{marginTop: '20px'}}>
<div className="row">
<div className="col-xs-4 col-xs-offset-1">
<Table list={this.state.list} edit={this.edit} deleteItem={this.deleteItem}></Table>
</div>
<div className="col-xs-3 col-xs-offset-1">
<Form name={this.state.name} handleChange={this.handleChange} submit={this.handleFormSubmit}></Form>
</div>
</div>
</div>
);
}
componentDidMount(){
this.query();
}
edit = (item) => {
const action =editUserAction(item);
store.dispatch(action)
}
query = () => {
const action = getAllUser();
store.dispatch(action);
}
deleteItem = (item) => {
store.dispatch(deleteUser(item.id));
}
handleChange = (name) =>{
const action = changeUsernameAction(name);
store.dispatch(action);
}
handleFormSubmit = (e) => {
e.preventDefault();
if(this.state.name !== ''){
let user = {
id:!this.state.id?'':this.state.id,
name:this.state.name
};
const action = saveUser(user);
store.dispatch(action);
}
}
}
export default App;
源码https://gitee.com/qinaichen/react-crud.git 中的redux-thunk
分支
网友评论