從零開始react實戰:雲書籤-1 react環境搭建
- 2019 年 10 月 3 日
- 筆記
????react ??????
??????
????????????????? react ????,?create-react-app
???????????
- antd ??????? ???????
- ?? less ?????? css-module
- ????
- ?? http ??
- ?? redux
??:?? node ???? 8.0.
?? create-react-app
- ??
npm install -g create-react-app
- ?? react ??
create-react-app bookmark-world
?????????????
?? antd,less
????????????????
- ??
npm run eject
?????????? ???????????????????????????. - ??
react-app-rewired
????.
??????????????–?????
??????
? 2.1.x ??? react-app-rewired ????customize-cra
???????????????????
- react-app-rewired ,????
- customize-cra ,????
- antd ,ui ?
- babel-plugin-import ,???? antd
- less ,less ??
- less-loader ,less ??
?????
npm install --save react-app-rewired customize-cra antd babel-plugin-import less less-loader
?? package.json
?react-app-rewired
??????react-scripts
/* package.json */ "scripts": { - "start": "react-scripts start", + "start": "react-app-rewired start", - "build": "react-scripts build", + "build": "react-app-rewired build", - "test": "react-scripts test", + "test": "react-app-rewired test", }
?? config-overrides.js
??????,???package.json
???????config-overrides.js
??.?????
const { override, fixBabelImports, addLessLoader } = require("customize-cra"); module.exports = override( fixBabelImports("import", { libraryName: "antd", libraryDirectory: "es", style: true }), addLessLoader({ localIdentName: "[local]--[hash:base64:5]", javascriptEnabled: true, modifyVars: { "@primary-color": "#1DA57A" } }) );
?? css-module
??? css-module ??? css ?????fileName.module.less
?????????????????????
????????????.module.less ??? css-module ???
import React, { Component } from "react"; import { Button } from "antd"; import styles1 from "./index.module.less"; class Hello extends Component { render() { return ( <div className={styles1.main}> hello <div className={styles1.text}>world</div> <Button type="primary">??</Button> <div className="text1">heihei</div> </div> ); } } export default Hello;
????
???? src ????????????
?????
- assets: ?????????????
- components???????
- layout: ??????????????????????
- pages: ??????
- redux??? redux ??
- action: ?? action
- reducer: ?? reducer ??
- util: ???
??serviceWorker.js
?????index.js
???????????????????????
????react-router
??:
cnpm install --save react-router-dom
?????????? react ???? js ????react-router-dom ??????????????????????history
???
????index.js
?????<BrowserRouter>
????? history ????????
// index.js import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import App from "./App"; import { BrowserRouter } from "react-router-dom"; const s = ( <BrowserRouter> <App /> </BrowserRouter> ); ReactDOM.render(s, document.getElementById("root"));
??????????????????????????????? App.jsx ?????????(????????????????????????)
???????????????????
render() { const mainStyle = { fontSize: "0.16rem" }; return ( <Provider store={store}> <div className="fullScreen" style={mainStyle}> <Switch> <Route exact path="/" component={Main} /> <Route exact path="/public/login" component={Login} /> <Route exact path="/404" component={NotFound} /> {/* ??????????????????/404 */} <Redirect path="/" to="/404" /> </Switch> </div> </Provider> ); }
?????
- Switch: ???????????????????????
- Route?????
- exact???????????????
/
???/
,????????? - Redirect????????????????????????????
exact
? path ?/
),??????/404
??????????????????????
?? http ????
http ??????????axios
?
???????
cnpm install --save axios
???????util/httpUtil.js
,?????
// httpUtil.js import { notification } from "antd"; import axios from "axios"; //??http?? const instance = axios.create({ // baseURL: "http://ali.tapme.top:8081/mock/16/chat/api/", headers: { token: window.token } }); //??????? instance.interceptors.response.use( function(res) { return res.data; }, function(error) { console.log(error); let message, description; if (error.response === undefined) { message = "????"; description = "???????"; } else { message = "????:" + error.response.status; description = JSON.stringify(error.response.data); //401??????? } notification.open({ message, description, duration: 2 }); setTimeout(() => { if (error.response && error.response.status === 401) { let redirect = encodeURIComponent(window.location.pathname + window.location.search); window.location.replace("/public/login?redirect=" + redirect); } }, 1000); return Promise.reject(error); } ); export default instance;
??????????
- ???? token???????? jwt ?????????????? token
- ????????????????????????? 401??????????
?? redux
redux ?? react ????????????? redux ????????????????????????.
???????????????????? reducer ???????? action ????????
????????????
??
- ???? action?????
redux/action/loginInfoAction.js
,?????
// ???????store???? export const DATA_NAME = "loginInfo"; //????loginInfo type export const CHANGE_LOGIN_INFO = "changeLoginStatus"; export const changeLoginInfo = (token, userInfo) => { return { type: CHANGE_LOGIN_INFO, data: { token, userInfo } }; };
- CHANGE_LOGIN_INFO :??????
- changeLoginInfo: ???? action?????????????????????? type ???? reducer ???.
- ?? reducer?????
redux/reducer/loginInfo.js
,?????
import * as loginAction from "../action/loginInfoAction"; function getInitData() { let token, userInfo; try { token = localStorage.getItem("token"); userInfo = JSON.parse(localStorage.getItem("userInfo")); } catch (e) { console.error(e); token = null; userInfo = null; } window.token = token; window.userInfo = userInfo; return { token, userInfo }; } const LoginStatusReducer = (state = getInitData(), action) => { switch (action.type) { case loginAction.CHANGE_LOGIN_INFO: return { ...action.data }; default: return state; } }; export default LoginStatusReducer;
- getInitData ??????? userInfo ??????????????? localeStore ?????????? window ????
httpUtil
??? token? - LoginStatusReducer ?????? action ??????????? loginInfo ???
- ?? reducer ???(redux/reducer/index.js)??? reducer ?????????????????????? store ????????
import { combineReducers } from "redux"; import { DATA_NAME } from "../action/loginInfoAction"; import loginInfo from "./loginInfo"; const data = {}; data[DATA_NAME] = loginInfo; const reducer = combineReducers(data); export default reducer;
- ??
redux/index.js
??????????????????
import { createStore } from "redux"; import reducer from "./reducer"; const store = createStore(reducer); export default store;
- ??? store ??????(App.js)???,???????
??
???????????????? loginInfo ??? loginInfo.
- ????????
pages/public/Login/index.js
????????
import React, { Component } from "react"; import queryString from "query-string"; import { Button, Input, message } from "antd"; import IconFont from "../../../components/IconFont"; import styles from "./index.module.less"; import { connect } from "react-redux"; import { changeLoginInfo, DATA_NAME } from "../../../redux/action/loginInfoAction"; import axios from "../../../util/httpUtil"; function mapStateToProps(state) { return state[DATA_NAME]; } function mapDispatchToProps(dispatch) { return { updateLoginInfo: (token, userInfo) => dispatch(changeLoginInfo(token, userInfo)) }; } class Login extends Component { constructor(props) { super(props); this.state = { username: "", password: "" }; this.query = queryString.parse(window.location.search); } usernameInput = e => { this.setState({ username: e.target.value }); }; passwordInput = e => { this.setState({ password: e.target.value }); }; submit = () => { axios.post("/public/login", this.state).then(res => { localStorage.setItem("token", res.token); localStorage.setItem("userInfo", JSON.stringify(res.userInfo)); window.token = res.token; window.userInfo = res.userInfo; message.success("????"); this.props.updateLoginInfo(res.token, res.userInfo); if (this.query.redirect) { this.props.history.replace(decodeURIComponent(this.query.redirect)); } else { this.props.history.replace("/"); } }); }; render() { return ( <div className="fullScreen flex main-center across-center"> // ?????? <Button type="primary" onClick={this.submit}> ?? </Button> ... </div> ); } } export default connect( mapStateToProps, mapDispatchToProps )(Login);
??????????????
- mapStateToProps:?????? store ???????????? Login ??? props ??
- mapDispatchToProps:??????? store ??????????????? Login ??? props ?,??? dispath ??????? reducer ????????? changeLoginInfo ??? action?
- connect ???????????? Login ???????????? props ?????????? withRouter,?? withRouter ??????
?????????? yapi ? mock ??????????????????
??
????????? react ???????????????
???github,??? tag:????????
???????????????
????????www.tapme.top/blog/detail/20190626