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

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} />
}
上一篇下一篇

猜你喜欢

热点阅读