美文网首页
webpack手动配置react app

webpack手动配置react app

作者: tikeyc | 来源:发表于2021-03-23 14:03 被阅读0次

    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} />
    }
    

    相关文章

      网友评论

          本文标题:webpack手动配置react app

          本文链接:https://www.haomeiwen.com/subject/ltszcltx.html