Songbao writes code

I. Project generation

  • create-react-app saucxs-webGenerating project
  • cd saucxs-webInto the project
  • yarn startStart the project

Ii. Project deployment

  • Local developmentyarn start
  • Online deploymentyarn build

Iii. Reference documents

  • React
  • create-react-app
  • Configuration reference for the Ant UI library
  • The react to the router in English
  • The react to the router in Chinese

4. Configuration items

1. Ant Design UI library introduction

  • yarn add antdThe installation UI library
  • yarn add babel-plugin-importImplement on-demand import

Add the following to package.json/ Babel:

"plugins": [["import",
        {
            "libraryName": "antd"."libraryDirectory": "es"."style": "css"}]]Copy the code

Components are used as follows:

import React, { Component } from 'react';
import { Button } from 'antd'
import 'antd/dist/antd.css'

class App extends Component {
  render() {
    return (
        <Button type="primary">Songbao writes code</Button>); }}export default App;
Copy the code

At this point, you can use the default style of the UI library

2. Customize Ant Design UI library styles

  • The installationlessless-loader
  • Using the commandyarn run ejectExposing profiles
  • inwebpack.config.dev.jswebpack.config.prod.jsTo make the following modifications:

createantModifyVars.jsfile

'use strict';

const modifyVars = {
  'primary-color': '#E26A6A',}module.exports = modifyVars;
Copy the code

To create less related variables, refer to the default sass configuration:

// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

// Add the less part
const lessRegex = /\.less/;
const lessModuleRegex = /\.module\.less$/;
Copy the code

Under oneOf in module.rules, append code like sass:

// Opt-in support for LESS (using .less extensions).
// Chains the less-loader with the css-loader and the style-loader
// to immediately apply all styles to the DOM.
// By default we support LESS Modules with the
// extensions .module.scss or .module.sass
{
    test: lessRegex,
    exclude: lessModuleRegex,
    use: getStyleLoaders({ importLoaders: 2 }, 'less-loader'),},// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
    test: lessModuleRegex,
    use: getStyleLoaders(
    {
        importLoaders: 2.modules: true.getLocalIdent: getCSSModuleLocalIdent,
    },
    'less-loader'),},Copy the code

In getStyleLoaders, handle less-loader

Configuration under // dev
if (preProcessor) {
    let loader = {loader: require.resolve(preProcessor)}
    if (preProcessor === "less-loader") {
        loader.options.modifyVars = modifyVars
        loader.options.javascriptEnabled = true
    }
    loaders.push(loader);
}

// Prod configuration
if (preProcessor) {
    let loader = {
         loader: require.resolve(preProcessor),
         options: {
            sourceMap: shouldUseSourceMap,
        },
    }
    if (preProcessor === "less-loader") {
        loader.options.modifyVars = modifyVars
        loader.options.javascriptEnabled = true
    }
    loaders.push(loader);
  }

Copy the code

3. ES6 API support introduces polyfills

Added support for ES6API in Internet explorer 9, Internet explorer 9+

Method one: Installationyarn add react-app-polyfill

// the [first line] in SRC /index.js introduces support for IE9 and later
import 'react-app-polyfill/ie9';

// Other support, such as support for IE11 and later
import 'react-app-polyfill/ie11';
Copy the code

Method two: Installationyarn add babel-polyfill

// webpack.base.conf.js introduces:
require("babel-polyfill")

// webpack.base.conf.js:
entry: { app: ['babel-polyfill'.'./src/main.js']}Copy the code

4. Introduce react-router-dom routes

  • react-router-domRely onreact-routerTherefore, when using NPM to install dependencies, you only need to install libraries in the corresponding environment instead of explicitly installing the React router.
  • Added because permission configuration is requiredAuthorizedRoute.jsControl over

5. Configure the alias with @ pointing to the SRC directory

The configuration of webpack.base.conf.js is the same as that of webpack.base.conf.js as follows:

ResolvePath (resolvePath); resolve name used in new versionfunction resolvePath (dir) {
  return path.join(__dirname, '.. ', dir)
}

// resolve. Alias:
The '@': resolvePath('src')
Copy the code

6. Introduce Axios

Add the following code at the bottom of package.json to resolve cross-domain issues

// Setupproxy. js is created in SRC with http-proxy-middleware.
// It is automatically referenced and no additional configuration is required
const proxy = require('http-proxy-middleware')

module.exports = function (app) {
  app.use(
    proxy(
      '/api', {
        target: 'http://**********'.changeOrigin: true}}))// Define multiple entries:
module.exports = function (app) {
  app.use(proxy('/api', { target: 'http://localhost:7001' }));
  app.use(proxy('/api2', { target: 'http://localhost:7001' }));
}
Copy the code

7. Style processing

Use react-CSS-modules to separate internal styles from external styles:

import React from 'react'
import CSSModules from 'react-css-modules';
import { Button } from 'antd'
import styles from './Header.module.scss'

class Header extends React.Component {
  render () {
    return (
      <div>
        <Button type="primary" className="nowrap" styleName="test">Songbao writes code</Button>
      </div>)}}export default CSSModules(Header, styles)
Copy the code

Note:

  • Since the latest create-React-app has been configured, there is no need to modify the WebPack configuration file
  • The above method can be implemented using both antD style, global style, and component private style
  • Pay special attention to the naming of component private style files[name].module.scss

Introduce stylus for create-React-app versions prior to 2.1.1

  • The installationstylusstylus-loader
  • Using the commandyarn run ejectExposing profiles
  • inwebpack.config.dev.jswebpack.config.prod.jsmodule/rules/oneOfTo modify the code:
{
    test: /\.(css|styl)$/,
        use: [
            require.resolve('style-loader'),
            {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1,}}, {loader: require.resolve('postcss-loader'),
                options: {
                    // Necessary for external CSS imports to work
                    // https://github.com/facebookincubator/create-react-app/issues/2677
                    ident: 'postcss'.sourceMap: true.plugins: () = > [
                        require('postcss-flexbugs-fixes'),
                        autoprefixer({
                            browsers: [
                            '> 1%'.'last 4 versions'.'Firefox ESR'.'not ie < 9'.// React doesn't support IE8 anyway].flexbox: 'no-2009',},],},}, {loader: require.resolve('stylus-loader'),
            options: {
                sourceMap: true,}},],},Copy the code

5. Problems encountered in the development process

1、warning提示:no-op

Refer to the content

Problem description

Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method

No – OP

Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component.

Status updates, such as asynchronous requests, events, timers, etc., cannot be performed on unmounted components, which should be cancelled during the componentWillUnmount life cycle

For events and timers, you only need to cancel event listening or clear timers in the componentWillUnmount method

The following solutions address the problems caused by asynchronous operations.

Option 1: use a variable [_isMounted] to control whether to update the status

import React from 'react'

class newComponent extends React.Component {
  _isMounted = false

  componentDidMount() {
    this._isMounted = true
    axios
      .get('https://hn.algolia.com/api/v1/search?query=react')
      .then(result= >
      if (!this._isMounted) return
        this.setState({
          news: result.data.hits,
        }),
      )
  }

  componentWillUnmount() {
    // Cancel event listener, clear timer, control asynchronous request
    this._isMounted = false
  }

  render() {
    return(...). }}export default newComponent
Copy the code

Plan 2: The rough way, directly change the setState function

import React from 'react'

class newComponent extends React.Component {

  componentWillUnmount() {
    // Cancel event listener, clear timer, control asynchronous request
    this.setState = () = > {
      return}}render() {
    return(...). }}export default newComponent
Copy the code

In scheme 3, the interface request can be cancelled directly, such as Axios CancelToken

2. Route redirects in different scenarios in React – Router4.0

reference

Plan one, officially recommended, is to use withRouter

import React from 'react'
import { withRouter } from 'react-router-dom'

class NewComponent extends React.Component {
  AFunction() {
    this.props.history.push('/path')}render() {
    return(...). }}export default withRouter(NewComponent)
Copy the code

Option two, not recommended, uses context

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router-dom'

class NewComponent extends React.Component {
  static contextTypes = {
    router: PropTypes.object
  }
  constructor(props, context) {
     super(props, context);
  }
  AFunction() {
    this.context.router.history.push('/path')}render() {
    return(...). }}export default NewComponent
Copy the code

Plan three, use history

In real service scenarios, non-React components often need to redirect routes. For example, in unified interface processing scenarios, users are redirected to the login page when their login fails.

Since the BrowserRouter component provided with React – Router4.0 creates history by default and does not expose it, using history in non-React situations will not work

So instead of using the BrowserRouter component, create your own history as follows:

  • To create the history
// SRC /history.js must be placed in the root directory of SRC
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
export default history
Copy the code
  • To configure the router
// SRC /index.js Note the history on the router
import { Router, Link, Route } from 'react-router-dom'
import history from './history'

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>.</Router>
  </Provider>.document.getElementById('root'),Copy the code
  • Other places to use, such as the interface Unified Processing layer
import history from '@/history';

export function addProduct(props) {
  return dispatch= >
    axios.post('xxx', props, config)
      .then(response= > {
        history.push('/cart')})}Copy the code

Read more

  • (55题) To achieve a full array of arrays

  • (54题) Maximum suborder sum

  • (53) A pair of k-diff numbers in an array

  • (52) Merge two ordered arrays

  • (51题) Maximum suborder sum

  • 2020 “Songbao Write Code” personal year-end summary: the future can be expected

Thank you for your support

1. If you like the article, you can “share it, like it, and read it”.

2, author nickname: SaucXS, songEagle, Songbao write code. “Songbao write code” public number author, daily question, laboratory, etc. A bytedance engineer who loves to toss, is committed to the whole stack, and is working hard to grow, star Sea, the future can be expected. Inside push bytedance each department each post.

3, pay attention to “Songbao write code”, is to acquire development knowledge system construction, selected articles, project actual combat, laboratory, a daily interview question, advanced learning, thinking about career development, involving JavaScript, Node, Vue, React, browser, HTTP, algorithm, end related, small program and other fields, hope to help you. We grow up together