webpack手动配置react app
2021-03-23 本文已影响0人
tikeyc
1.集成react相关
yarn add react react-dom react-router-dom prop-types reach-router-hash-history
yarn add axios cookies-js classnames echarts echarts-for-react moment
2.新建router文件夹和组件router/router.js
import React from 'react';
import {
BrowserRouter as Router,
Route,
Switch,
Link,
} from 'react-router-dom';
import Home from '../pages/Home';
import Test from '../pages/Test';
const getRouter = () => (
<Router>
<div>
<ul>
<li><Link to="/">首页</Link></li>
<li><Link to="/Test">Test</Link></li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/Test" component={Test} />
</Switch>
</div>
</Router>
);
export default getRouter;
3.集成react-redux
yarn add redux react-redux redux-axios-middleware
4.先来写action创建函数。通过action创建函数,可以创建action
src/redux/actions/counter.js
const ACTION_PREFIX = module.id; // 设置action前缀确保type的唯一性
// console.log('ACTION_PREFIX1', ACTION_PREFIX);
export const INCREMENT = `${ACTION_PREFIX}/INCREMENT`;
export const DECREMENT = `${ACTION_PREFIX}/DECREMENT`;
export const RESET = `${ACTION_PREFIX}/RESET`;
export function increment() {
return { type: INCREMENT };
}
export function decrement() {
return { type: DECREMENT };
}
export function reset() {
return { type: RESET };
}
再来写reducer,reducer是一个纯函数,接收action和旧的state,生成新的state.
src/redux/reducers/couter.js
import { INCREMENT, DECREMENT, RESET } from '../actions/counter';
/*
* 初始化state
*/
const initState = {
count: 0,
};
/*
* reducer
*/
export default function reducer(state = initState, action) {
switch (action.type) {
case INCREMENT:
return {
count: state.count + 1,
};
case DECREMENT:
return {
count: state.count - 1,
};
case RESET:
return { count: 0 };
default:
return state;
}
}
一个项目有很多的reducers,我们要把他们整合到一起
reducer就是纯函数,接收state 和 action,然后返回一个新的 state
src/redux/reducers.js
import counter from './reducers/couter';
export default function combineReducers(state = {}, action) {
return {
counter: counter(state.counter, action),
};
}
5.创建一个store
- 提供 getState() 方法获取 state;
- 提供 dispatch(action) 触发reducers方法更新 state;
- 通过 subscribe(listener) 注册监听器;
- 通过 subscribe(listener) 返回的函数注销监听器
src/redux/store.js
import { createStore } from 'redux';
import combineReducers from './reducers';
const store = createStore(combineReducers);
export default store;
6.传入store
使用指定的 React Redux 组件 来 让所有容器组件都可以访问 store,而不必显示地传递它。只需要在渲染根组件时使用即可
src/index.js
import '@babel/polyfill';
import React from 'react';
import ReactDom from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import getRouter from './router';
import './style/style.less';
ReactDom.render(
<Provider store={store}>{getRouter()}</Provider>,
document.getElementById('root'),
);
if (module.hot) {
console.log('module.hot.accept');
// 实现热更新
module.hot.accept();
}
7.写一个Counter页面,然后修改路由,增加Counter
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { increment, decrement, reset } from '../../redux/actions/counter';
class Counter extends Component {
componentDidMount() {}
render() {
return (
<div>
<div>当前计数为(显示redux计数)</div>
<button
type="button"
onClick={increment()}
>
自增
</button>
<button
type="button"
onClick={decrement()}
>
自减
</button>
<button
type="button"
onClick={reset()}
>
重置
</button>
</div>
);
}
}
const mapStateToProps = state => ({
counter: state.couter,
});
const mapDispatchToProps = dispatch => ({
increment: () => {
dispatch(increment());
},
decrement: () => {
dispatch(decrement());
},
reset: () => {
dispatch(reset());
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Counter);
8.引入异步action,集成redux-thunk
yarn add redux-thunk
简单的说,中间件就是action在到达reducer,先经过中间件处理。我们之前知道reducer能处理的action只有这样的{type:xxx},所以我们使用中间件来处理
函数形式的action,把他们转为标准的action给reducer。这是redux-thunk的作用。
使用redux-thunk中间件
src/redux/store.js
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import combineReducers from './reducers';
const store = createStore(combineReducers, applyMiddleware(thunkMiddleware));
export default store;
import { connect } from 'react-redux';
import * as actions from './actions';
import Counter from './components';
const mapStateToProps = ({ counter }) => ({
...counter,
});
// const mapDispatchToProps = dispatch => ({
// add: () => {
// dispatch(increment());
// },
// deleted: () => {
// dispatch(decrement());
// },
// set: () => {
// dispatch(reset());
// },
// getUserInfo: () => {
// dispatch(test());
// },
// });
export default connect(mapStateToProps, actions)(Counter);
9.引入异步action 集成redux-axios-middleware和axios
yarn add redux-axios-middleware
详情配置见redux文件夹(store、axios)
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
// import axiosMiddleware from 'redux-axios-middleware';
import { multiClientMiddleware } from 'redux-axios-middleware';
import createAxios from './axios';
import combineReducers from './reducers';
let clients = {
default: {
client: createAxios({
baseURL: 'dev/api',
}),
},
};
const options = {};
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
if (process.env.NODE_ENV === 'production') {
clients = {
default: {
client: createAxios({
baseURL: '/api',
}),
},
};
}
const store = createStore(
combineReducers,
applyMiddleware(
thunkMiddleware,
multiClientMiddleware(clients, options),
),
);
export default store;
10 热更新(配置见webpack.config.base.js)
https://github.com/gaearon/react-hot-loader
yarn add react-hot-loader
11 ...rest属性传递配置
yarn add @babel/plugin-proposal-object-rest-spread -D
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }
yarn add babel-plugin-transform-react-handled-props -D
const Foo = (props) => {
const { className, ...rest } = props
const classes = classNames(className, 'foo')
return <div {...rest} className={classes} />
}