Used by the React Hooks child component
Get children from the argument and render directly with {children}
Webpack enables the CSS Module
module:{
rules:{
{
test: /\.(sa|sc)ss$/,
exclude: /node_modules/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
reloadAll: true,
esModule: true,
modules: {
namedExport: true,
},
}
},
{
loader: "css-loader",
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]',
exportGlobals: true,
namedExport: true,
},
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
},
]
},
}
}
Copy the code
Using CSS module
import * as style from "./index.module.scss"
<div className={style.container}/>
Copy the code
Commit the canonical
Commitizen use
Commitizen is a tool for writing qualified Commit messages
npm install -g commitizen
Copy the code
Use in the project directory:
commitizen init cz-conventional-changelog --save --save-exact
Copy the code
Use git cz instead of git commit
Generate the changelog:
$ npm install -g conventional-changelog-cli
$ cd my-project
$ conventional-changelog -p angular -i CHANGELOG.md -s
Copy the code
Mobile fit problem
Flexible huawei mobile phone may have various style issues, cooperate with React use postCSS-pxtoREM conversion REM
Width, height, spacing with percentages as far as possible
Add wechat restrictions
export const addWeixinLimit = () = > {
if (process.env.NODE_ENV === 'production') {
let ua = navigator.userAgent.toLowerCase();
let isWeixin = ua.match(/micromessenger/i) = ='micromessenger' && (ua.match(/wxwork/i) != 'wxwork');
if(! isWeixin) {document.head.innerHTML = '< title > I'm sorry,
< link rel =" stylesheet "type =" text/CSS "href =" https://res.wx.qq.com/open/libs/weui/0.4.1/weui.css "> ';
document.body.innerHTML = '
Please open the link on wechat client
'; }}}Copy the code
Configure the react – hot – loader
After installation, add in the.babelrc file
"plugins": [["react-hot-loader/babel"]]Copy the code
Wrap the App root component in the index.js file
import { hot } from 'react-hot-loader/root';
const HotApp = hot(
() = > <Provider store={store}>
<App />
</Provider>
)
ReactDOM.render(
<HotApp />.document.getElementById('root'));Copy the code
The react to the router configuration
Configure the asynchronous load routing component and create an AsyncComponent
import React, { Component } from "react";
export default function asyncComponent(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {. this.props} / > : null; }}return AsyncComponent;
}
Copy the code
Introduced in route.js
import AsyncComponent from '@/components/common/AsyncComponent'
const Home = AsyncComponent(() = > import('@/pages/Home'))
Copy the code
Page routing resets the scroll bar to the top
Create the ScrollToTop.js component
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
class ScrollToTop extends Component {
componentDidUpdate(prevProps) {
if (this.props.location.pathname ! == prevProps.location.pathname) {window.scrollTo(0.0); }}render() {
return this.props.children; }}export default withRouter(ScrollToTop);
Copy the code
Wrap a layer of route during route rendering
import ScrollToTop from "@/utils/ScrollToTop.js"
function RenderRouters({ routes }) {
return routes.map((item) = >
<ScrollToTop
key={item.name}
><Route
path={item.path}
render={()= > (<item.component />)
} />
</ScrollToTop>)}Copy the code
Embedded routines by
<Switch>
<Redirect exact from='/score' to='/score/step' />
<Route path="/score/step"/>
<Switch/>
Copy the code
Remember not to use exact matching of nested routines, otherwise you will find no sub-routes
Configuration redux
Create types
export default {
/* * Loading status * COMMON * Loading Begins * Loading ends * */
LOADING_START: 'LOADING_START'.LOADING_END: 'LOADING_END'.// Get forum data
FETCH_FORUM: 'FETCH_FORUM'
}
Copy the code
Create the actions
import commonTypes from "@/store/types/common"
import { getForumData } from "@/api/common"
export function startLoading() {
return {
type: commonTypes.LOADING_START,
}
}
export function endLoading() {
return {
type: commonTypes.LOADING_END,
}
}
// Get forum information
export function getForum() {
return (dispatch) = > {
return getForumData().then((res) = > {
dispatch({
type: commonTypes.FETCH_FORUM,
payload: res.data
})
return res.data
})
}
}
Copy the code
Create the reducer
import commonTypes from "@/store/types/common"
const initialState = {
isLoading: false.forumData: {}};function commonReducer(state = initialState, action) {
switch (action.type) {
case commonTypes.LOADING_START:
return {
...state,
isLoading: true};case commonTypes.LOADING_END:
return {
...state,
isLoading: false};case commonTypes.FETCH_FORUM:
return {
...state,
forumData: action.payload
};
default:
return state
}
}
export default commonReducer;
Copy the code
Integration of the reducer
import { combineReducers } from 'redux'
import common from './common'
import user from './user'
export default combineReducers({
common,
user
})
Copy the code
Create the store
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducers'
import thunk from 'redux-thunk'
const configureStore = (preloadedState) = > createStore(
reducer,
preloadedState,
compose(
applyMiddleware(thunk),
)
)
export default configureStore()
Copy the code
The root node passes in store
import { Provider } from 'react-redux'
import store from '@/store'
<Provider store={store}>
<App />
</Provider>
Copy the code
Introduce use through CONNECT
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as CommonAction from '@/store/actions/common';
class App extends Component {
componentDidMount() {
console.log(this.props)
let token = LocalStorageUtil.get('token')}render() {
const { isLoading } = this.props;
const renderContent = (<BrowserRouter>
<Fragment>
<Route exact path="/" render={()= > (
<Redirect to="/home" />)} / ><RenderRouters routes={routes}></RenderRouters>
</Fragment>
</BrowserRouter>)
return (
<div className="App">
{
isLoading
? (<ActivityIndicator
toast
text="Loading..."
animating={isLoading}
/>)
: renderContent
}
</div>)}}const mapStateToProps = (state, props) = > ({
isLoading: state.common.isLoading,
})
const mapDispatchToProps = (dispatch) = > ({
...bindActionCreators(CommonAction, dispatch)
})
export default (connect(mapStateToProps, mapDispatchToProps)(App));
Copy the code
Introduced via React hooks
import { useDispatch, useSelector } from "react-redux";
import { getForum } from "@/store/actions/common"
const { formData } = useSelector(state= > state.user)
const dispatch = useDispatch()
dispatch(getForum())
Copy the code
Configure webPack packaging optimization
Configuration HtmlWebpackPlugin
new HtmlWebpackPlugin({
filename: utils.resolve('.. /dist/index.html'),
template: 'public/index.html'.inject: true.hash: true.minify: {
removeComments: true.collapseWhitespace: true.removeAttributeQuotes: true}}),Copy the code
Configure splitChunks, JS compression, and CSS compression
optimization: {
minimize: true.minimizer: [
new TerserPlugin({ Js / / compression
parallel: true
}),
/ / compress CSS
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
discardComments: { removeAll: true } // Remove comments}}),].splitChunks: {
chunks: "async".minSize: 30000.minChunks: 1.maxAsyncRequests: 5.maxInitialRequests: 3.automaticNameDelimiter: '~'.name: true.cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2.priority: -20.reuseExistingChunk: true}}}}Copy the code
Use antD-Mobile + RC-form
Using InputItem
import { InputItem, Toast, Modal } from 'antd-mobile';
import { createForm } from 'rc-form';
const { getFieldProps, getFieldValue, validateFields, getFieldError } = props.form;
<InputItem
{. getFieldProps('phone'{initialValue: formData.phone.rules: [{ required: true.message:'Please enter mobile phone number'}, {validator: (rule.value) = >IsPhoneNumber (value.replace(/\s+/g, "")), message: 'please input the appropriate phone number'}]})} type="phone" placeholder=" please input the appropriate phone number "><span className={style.formText}>Mobile phone number<span className={style.required}>*</span></span></InputItem>
Copy the code
Use validateFields for validation
validateFields(async (error, value) => {
for (const key of Object.keys(value)) {
if (error && error[key] && error[key].errors.length > 0) {
for (const err of error[key].errors) {
Toast.fail(err['message'])
return; }}}})Copy the code
If you use CSS Modules, change the default style with :global global injection
:global {
.am-list-item{
background-color:transparent! important; }}Copy the code
conclusion
This project was to build react from scratch. During the building process, I reviewed webpack again and learned some skills of React configuration, so as to get better acquainted with React