安装react
create-react-app <项目名>
修改启动端口
在package.json文件修改scripts-start 为 "start": "set PORT=8081 && react-scripts start"
安装redux redux-saga react-redux react-router-dom
npm install redux redux-saga react-redux react-router-dom --save
or yarn add redux
redux
Redux 是 JavaScript 状态容器,提供可预测化的状态管理
安装稳定版:npm install --save redux
redux-saga
是一个用于管理应用程序 Side Effect(副作用,例如异步获取数据,访问浏览器缓存等)的 library,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。
安装
$ npm install --save redux-saga或
$ yarn add redux-saga
react-redux
实际项目中,需要权衡是直接使用Redux还是用React-Redux。
React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)
React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)
作者:kiterumer
链接:https://www.jianshu.com/p/ad7eddb23d66
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
配置redux
在src 下面新增Store文件
Store 下新加如下文件
actionCreators.js (定义一些方法)
actionTypes.js(定义一些匹配类型)
index.js(配置redux saga react-redux的核心文件)
reducer.js(定义具体实现方法)
saga.js(配置saga文件)

配置Store
actionType.js配置
export const INIT_LIST_ITEM_SAGA = 'init_list_item_saga' /*运用saga初始化数据*/
export const INIT_LIST_ITEM = 'init_list_item' /*初始化数据*/
actionCreators.js配置
import { INIT_LIST_ITEM_SAGA } from './actionTypes'
export const initListActionSaga = () => ({
type: INIT_LIST_ITEM_SAGA
})
reducer.js配置
import { INIT_LIST_ITEM } from './actionTypes'
//默认数据
const defaultState = {
name: '123',
list: [1, 2, 3, 4, 5, 6]
}
export default (state = defaultState, action) => {
let newStats = null
if (action.type === INIT_LIST_ITEM) {
newStats = JSON.parse(JSON.stringify(state))
newStats.list = action.list
return newStats
}
}
index.js配置
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from './reducer'
// 使用saga
import createSagaWiddleware from 'redux-saga'
import mySaga from './saga'
const sagaMiddleware = createSagaWiddleware()
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware))
const store = createStore(reducer, enhancer)
sagaMiddleware.run(mySaga)
export default store
saga.js配置
import { put, takeEvery } from 'redux-saga/effects'
import { INIT_LIST_ITEM_SAGA, INIT_LIST_ITEM } from './actionTypes'
let promist = function() {
debugger
return new Promise((resolve, reject) => {
resolve([1, 3, 4, 5, 6, 7, 8, 9])
})
}
function* getListFun() {
const list = yield promist()
yield put({
type: INIT_LIST_ITEM,
list
})
}
function* mySaga() {
yield takeEvery(INIT_LIST_ITEM_SAGA, getListFun)
}
export default mySaga
配置完毕
调用
修改根目录主文件index.js
import React from 'react'
import ReactDOM from 'react-dom'
// 引用 store
import store from './Store'
import { Provider } from 'react-redux'
import Index from './Components/index'
const App = (
<Provider store={store}>
<Index />
</Provider>
)
ReactDOM.render(App, document.getElementById('root'))
在src 下面创建 Components文件夹 以及在Components下创建index.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
// import { Switch, Route, BrowserRouter } from 'react-router-dom'
import { initListActionSaga } from '../Store/actionCreators'
class Index extends Component {
constructor(prop) {
super(prop)
this.state = {}
}
render() {
return <div>123123</div>
}
}
/*mapDispatchToProps 将redux里面的所有的action 配发给所有的组件*/
const mapDispatchToProps = dispatch => {
return {
initListSaga() {
const action = initListActionSaga()
dispatch(action)
}
}
}
const mapStateToProps = state => {
return {
list: state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Index)
现在为止 react + react-redux + redux-saga 项目配置完毕
saga调用数据
import React, { Component } from 'react'
import { connect } from 'react-redux'
// import { Switch, Route, BrowserRouter } from 'react-router-dom'
import { initListActionSaga } from '../Store/actionCreators'
class Index extends Component {
constructor(prop) {
super(prop)
this.state = {}
}
getList() {
this.props.initListSaga()
}
componentWillMount() {
this.getList()
}
render() {
let list = this.props
console.log(list)
return <div>123123</div>
}
}
/*mapDispatchToProps 将redux里面的所有的action 配发给所有的组件*/
const mapDispatchToProps = dispatch => {
return {
initListSaga() {
const action = initListActionSaga()
dispatch(action)
}
}
}
const mapStateToProps = state => {
return {
list: state.list
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Index)
代理配置
安装
npm install http-proxy-middleware --sava
or yarn add http-proxy-middleware
src建setupProxy
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
// ...You can now register proxies as you wish!
app.use(proxy('/hsDeposit', {
target: 'http://192.168.1.155:3000',
changeOrigin: true,
pathRewrite: {
"/hsDeposit": ""
},
}));
};
src建util/http.js
安装axios
import axios from 'axios'
let baseUrl = ''
if (process.env.NODE_ENV === 'development') {
/*本地*/
baseUrl = '/hsDeposit'
// baseUrl = "http://192.168.8.36:8080/";
} else {
baseUrl = ''
/*生产*/
// baseUrl = "http://192.168.1.86:8000/v1";/*生产*/
}
// axios 配置
//axios.defaults.timeout = 5000;
//axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
//axios.defaults.baseURL = 'http://192.168.10.101:8888/app';
axios.defaults.withCredentials = true
// 请求超时拦截器
axios.interceptors.request.use(
config => {
return config
},
error => {
return Promise.reject(error.response)
}
)
// 请求完成后的拦截器
axios.interceptors.response.use(
response => {
return response
},
error => {
// 这里我们把错误信息扶正, 后面就不需要写 catch 了
return Promise.resolve(error.response)
}
)
function checkStatus(response) {
// loading
// 如果http状态码正常,则直接返回数据
if (
response &&
(response.status === 200 ||
response.status === 304 ||
response.status === 400)
) {
return response.data
// 如果不需要除了data之外的数据,可以直接 return response.data
}
// 异常状态下,把错误信息返回去
return {
status: -404,
msg: '无法连接到服务器'
}
}
export default {
post(url, data, rollBack) {
return axios({
method: 'post',
// baseURL: 'http://192.168.1.223:8000/v1',//(ip)
baseURL: baseUrl, //(生产)
url,
data: data,
// dataType: "json",
timeout: 60000,
headers: {
'Access-Control-Allow-Origin': '*',
// 'Access-Control-Max-Age': '1209600',
// 'Content-Type': 'multipart/form-data'
'Content-Type': 'application/json'
}
})
.then(response => {
return rollBack(checkStatus(response))
})
.catch(res => {
// return rollBack("error")
})
},
get(url, params, rollBack) {
return axios({
method: 'get',
baseURL: baseUrl, //(生产)
// baseURL: 'http://192.168.1.171:8888/app',
url,
headers: {
// 'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
// 'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Max-Age': '1209600'
},
params, // get 请求时带的参数
timeout: 60000
})
.then(response => {
return rollBack(checkStatus(response))
})
.catch(res => {
// return rollBack("error")
})
}
}
数据请求
修改 src/Store/saga.js
let promist = function() {
return new Promise((resolve, reject) => {
http.get('/api/shop', {}, data => {
if (data.responeStatus === '0') {
resolve(data.data.list)
}
})
})
}
路由配置
import { Switch, Route, BrowserRouter } from 'react-router-dom'
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/Home" component={Home} />
</Switch>
</BrowserRouter>