首页 > 其他分享 >React

React

时间:2024-05-30 11:32:39浏览次数:25  
标签:return counter React state import 组件 const

react 依赖

  • react-native 移动端跨平台
  • 16.13.1版本
  1. react: 核心代码
  2. react-dom: 渲染在不同平台需要的核心代码
  3. babel:jsx转换react代码工具
//crossorigin 在控制台显示远程的错误信息
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
 ReactDom.render(<App/>,documnet.getElementById('root'))
</script>
//1有继承extends,子类必须调用super()
class Person {
    constructor(name,age){
        this.name=name;
        this.age=age;
    }
}

class Student extends Person{
    constructor(name,age){
    super(name,age)
}
}
jsx核心语法

书写规范:

  1. 只能有一个根元素div(或者用Fragment)片段,空标签占位
  2. 用小括号包裹
  3. 可以写双标签,或者单标签,必须/>结尾
{js表达式}

1.注释书写:
{/*我是一段注释*/}

2.在{}中不能显示,被忽略
test1:null
test2:undefined
test3:Boolean
friend:{
    name:'kobe'
}
this.setState.test3.toString()可以展示在页面
this.setState.friend //报错,对象不能直接这样展示 ,不能作为jsx的子类

3.嵌入表达式
{/*三元表达式*/}
{isLogin?'欢迎':'登录'}

{/*函数调用*/}


4.jsx绑定属性className 
<div className ='' style={{color:'red',fontSize:'30px'}}></div>
<label htmlFor=''></label>
//方式一,显示绑定
<button  onClick={this.btnClick.bind(this)}></button>


//方式二
this.btnClick=this.btnClick.bind(this)
<button  onClick={this.btnClick}></button>
<button  onClick={(e)=>{this.btnClick(item,index)}}></button>//执行另外一个函数 --推荐
//只要一个参数(e),括号可以省略 e=>{}
    btnClick(item,index){
        
    }

//方式三  推荐
<button  onClick={this.btnClick></button>
const btnClick=()=>{

} 

5.传递参数

6.return () 用小括号包裹起来,标签可以换行

7.条件渲染
  // 1.方案一:通过if判断: 逻辑代码非常多的情况
    let welcome = null;
    let btnText = null;
    if (isLogin) {
      welcome = <h2>欢迎回来~</h2>
      btnText = "退出";
    } else {
      welcome = <h2>请先登录~</h2>
      btnText = "登录";
    }
 {/* 2.方案二: 三元运算符 */}
 <button onClick={e => this.loginClick()}>{isLogin ? "退出" :"登录"}</button>
 
 {/* 3.方案三: 逻辑与&& */}
{/* 逻辑与: 一个条件不成立, 后面的条件都不会进行判断了 */}
    <h2>{ isLogin && "你好啊, coderwhy" }</h2>
    { isLogin && <h2>你好啊, coderwhy</h2> }

react脚手架:create-react-app 项目名称(dccweb-hd)不允许大写字母

npm yarn
npm install yarn install
npm install yarn add

PWA 离线

serviceWork.js

yarn eject 暴露webpack配置信息 此操作不可逆

组件的生命周期

生命周期 
类组件:可以维护数据状态,有this
函数没有生命周期,没有this,不能管理数据状态
类里面的叫方法,有this绑定
外部叫函数

挂载阶段 mounting 
constroct
cwm→	componentWillMount = () => { } DEPRECATED!!! 过时的
cdm→	componentDidMount = () => { }  *****

cwr→	componentWillReceiveProps = (nextProps) => { } DEPRECATED!!!

更新阶段 Updating
scu→	shouldComponentUpdate = (nextProps, nextState) => { }
cwup→	componentWillUpdate = (nextProps, nextState) => { } DEPRECATED!!!
cdup→	componentDidUpdate = (prevProps, prevState) => { } *****

卸载Unmount 
cwun→	componentWillUnmount = () => { } 

组件的数据传递

父子组件的通信
父组件通过属性=值 prodectList={prodectList}
子组件props参数获取
function Main(props) {
    const {prodectList}=props


子组件传递父组件
父组件 itemClick={函数}
子组件 执行函数

// 父组件里调用子组件 是否允许ppt向下惯性运动
  const flagRef = useRef(true);//是否允许ppt向下惯性运动,默认true,允许,点击一键置顶按钮时,不允许
  const getIsInertiaMove = (val: boolean) => {
    flagRef.current = val;
  };
 <Topping
          parentCallback={getIsInertiaMove}
          currScrollPos={currScrollPosY}
 />
 
 //子组件接收
 interface IToppingProps {
  currScrollPos: any;
  parentCallback: Function;
}
function Topping(props: IToppingProps) {
  const { currScrollPos, parentCallback } = props;
  
   // 触发一键置顶按钮,不允许向下惯性运动
   parentCallback(false);
  }
  

跨组件通信
1.props,一级一级传值
2.属性展开:jsx语法
const props={firstName='hobby',lastName='Hector'}
<ProfileHeader {...props}/>
<ProfileHeader firstName="Ben" lastName="Hector" />

3.Context:★
类组件
    第一步:创建 export const WordContext = createContext({} as IMobSignContext);
 <WordContext.provider value={}>
    <Profile/> //不包含在这个里面,传递的就是默认值
 <WordContext.provider/>
 第二步:
 ProfileHeader.contextType=WordContext;
 
  this.context

函数组件:
consumer

后续用redux替代 ★






//插槽 slot
<NavBar>
    <span></span>
    <div></div>
</NavBar>


this.props.children 获取组件内部标签

跨组件事件传递 events

yarn add events
API
创建对象:eventBus
import { EventEmitter } from 'events';
const eventBus = new EventEmitter();

发出事件eventBus.emit("事件名称",参数列表)
监听事件eventBus.addListener("事件名称",监听函数)
移除事件:eventBus.removeListener("事件名称",监听函数)

setState

setState是异步更新的
提高性能:获取多个更新,然后批量更新
如果同步,不能保证render和props同步,不能保证state和props一致性

 this.setState({
     message:'你好啊'
 },()=>{
     //拿到异步的数据,类似vue里面的nextTick
     console.log(this.state.message)
 })
 componentDidUpdate()方式二:获取异步数据
 
 同步更新:
 放在定时器里面执行,变成同步
 
 
 数据合并:传对象
 setState内部合并:
 
 累计合并:传函数
 setState((preState,props)=>{
    return{
        counter:preState.counter+1
    }
 })
 

react性能优化

函数组件:memo包裹
counter改变,包裹memo的组件不会重新渲染

类组件:extends PureCompontent


Ref

React.createRef()
current 获取元素

react中的CSS

CSS in js
yarn add styled-components

style.ts
import styled from 'styled-components';

export const BtnWrapper = styled.div<{ isActive: boolean; activeBgi: any }>`
    border: ${(props) =>props.isActive ? '0.05rem solid #0181ff' : '0.05rem solid red'};
    span{
        &.active{
            color:red //表示同时是span并且有active
        }
    }
`;
<BtnWrapper>
<BtnWrapper/>


react 添加class
/**
 * 特点:
 *  1.props穿透
 *  2.attrs的使用
 *  3.传入state作为props属性
 */

const HYInput = styled.input.attrs({
  placeholder: "coderwhy",
  bColor: "red"
})`
  background-color: lightblue;
  border-color: ${props => props.bColor};
  color: ${props => props.color};
`
<HYInput type="password" color={this.state.color}/>

高级用法:
1.继承 
styled(HYInput)`
`
2.设置主题
import styled {ThemeProvider} from 'styled-components';
<ThemeProvider theme={{themeColor:'red',fontSize:'20px'}}>
<ThemeProvider/>

color: ${(props) =>props.theme.themeColor}
 
 
 动态添加classNames
三元表达式
第三方库:classNames★

classNames({foor:true})
className={classNames(['clear', { iconActive: isBtnActive }])}

 <div
      className={classnames({
        [styles.sheet]: true,
        [styles.active]: current.sheetId == v.sheetId,
      })}
    >
    
const active = useMemo(
  () =>
  classNames({
      [styles.active]: activeCurrentPage===activeIndex,
    }),
  [activeCurrentPage],
);

  • webpack下,import store from './store/index.js'
  • index.js可以省略。,import store from './store'
  • import * as actionType from './constants'; actionType.
import {
  incAction,
  addAction,
  changeBannersAction,
  changeRecommendAction
} from '../store/actionCreators'

redux

  //★actionCreators
 export const addAction = num => ({
  type: ADD_NUMBER,
  num
});

 //★constants  //export const ADD_NUMBER = "ADD_NUMBER";
 //★index
 
 //★reducer
 // 拆分counterReducer
const initialCounterState = {
  counter: 0
}
function counterReducer(state = initialCounterState, action) {
  switch (action.type) {
    case ADD_NUMBER:
      return { ...state, counter: state.counter + action.num };
    case SUB_NUMBER:
      return { ...state, counter: state.counter - action.num };
    case INCREMENT:
      return { ...state, counter: state.counter + 1 };
    case DECREMENT:
      return { ...state, counter: state.counter - 1 };
    default:
      return state;
  }
}

export default counterReducer;

 
import { useSelector, shallowEqual } from 'react-redux';
import reducer, { defaultState } from './reducer';
import React, {
  memo,
  useRef,
  useState,
  useReducer,
  useContext,
  useCallback,
  useMemo,
  useEffect,
  useLayoutEffect,
} from 'react';



store
const init={
    friend:[
    {name:'why'}
    ]
}
import reducer from './reducer.js';
const store = redux.createStore(reducer);

一般会有多个reducer,需要合并


action
派发(dispatch())action 更新
const action1={type:'ADD_FRIEND',info:{name:'lucy'}}
store.dispatch(action1)


---
---
reducer 纯函数,不能产生副作用
reducer将sotre和action 联系起来
import {
  ADD_NUMBER,
  SUB_NUMBER,
  INCREMENT,
  DECREMENT
} from './constants.js';

const defaultState = {
  counter: 0
}

function reducer(state = defaultState, action) {
  switch (action.type) {
    case ADD_NUMBER:
      return { ...state, counter: state.counter + action.num };
    case SUB_NUMBER:
      return { ...state, counter: state.counter - action.num };
    case INCREMENT:
      return { ...state, counter: state.counter + 1 };
    case DECREMENT:
      return { ...state, counter: state.counter - 1 };
    default:
      return state;
  }
}

export default reducer;

中间件:redux-thunck

hooks

useState
useEffect
useContext
useReducer
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
自定义hooks

useSelector
import { useSelector } from 'umi';
import { useSelector, shallowEqual } from 'react-redux';

★useState  返回一个数组 
* 元素1: 当前state的值
* 元素2: 设置新的值时,使用的一个函

<React.StricMode>
    <App/>
<React.StricMode/>
严格模式下,render会被渲染两次

注意:不要再函数,条件判断,for循环里面使用hooks
  const [counter,setCounter]=useState(0) 
  setCounter(counter+1)
  
  传入函数
const [count, setCount] = useState(() => 10);
 setCount((prevCount) => prevCount + 10);
  
  usestate 快捷键,按下tab键
  
  
 ★useEffect  生命周期
 
 
  useEffect(() => {
    console.log("订阅一些事件");
    
    //生命周期 componentWillUnmount
    return () => {
      console.log("取消订阅事件")
    }
  }, []);
    []表示第一次渲染的时候执行一次;如果不写,只要组件重新渲染,都会执行一遍

 ★useContext 子孙组件传递数据
 export const UserContext= createContext()
 export const PcSignContext = createContext({} as IPcSignContext);
  {/* <UserContext.Provider value={{name: "why", age: 18}}>
        <TokenContext.Provider value="fdafdafafa">
          <CustomContextShareHook/>
        </TokenContext.Provider>
      </UserContext.Provider> */}
 
 
  const user = useContext(UserContext);
  const theme = useContext(ThemeContext);



★useReducer  是useState的一种替代方案 不共享state
  const [state, dispatch] = useReducer(reducer, {counter: 0});
  dispatch({type: "increment"})}

export default function reducer(state, action) {
  switch(action.type) {
    case "increment":
      return {...state, counter: state.counter + 1};
    case "decrement":
      return {...state, counter: state.counter - 1};
    default:
      return state;
  }
}


★useCallback 性能优化 针对函数 meno
场景: 在将一个组件中的函数, 传递给子元素进行回调使用时, 使用useCallback对函数进行处理.
 const increment2 = useCallback(() => {
    console.log("执行increment2函数");
    setCount(count + 1);
  }, [count]);
//也可以用useMome
  const increment3 = useMemo(() => {
    return () => {
      console.log("执行increment2函数");
      setCount(count + 1);
    }
  }, [count]);

★useMemo  性能优化 针对返回值,返回记忆值
复杂计算的应用
  const total = useMemo(() => {
    return calcNumber(count);
  }, [count]);
  
  
传入子组件  或者用useState
  const info = useMemo(() => {
    return { name: "why", age: 18 };
  }, []);
  <HYInfo info={info} />
  
  
 ★useRef 只能在class组件中使用,在函数式组件中使用需要用forwardRef包裹
   const titleRef = useRef();
   
function changeDOM() {
    titleRef.current.innerHTML = "Hello World";
    inputRef.current.focus();
    console.log(testRef.current);
    console.log(testRef2.current);
  }

    <h2 ref={titleRef}>RefHookDemo01</h2>
    
    *** const numRef = useRef(count);
      useEffect(() => {
        numRef.current = count;
      }, [count])
    //保存一个函数,在整个生命周期中保存不变
    使用场景:记录上一次的值
    
    
    
★useImperativeHandle 和forwardRef关联 目的不过多暴露给父组件
forwardRef 可以将ref转发到子组件

const HYInput = forwardRef((props, ref) => {
  const inputRef = useRef();

//()用小括号包裹起来,返回的是一个对象
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }), [inputRef])

  return <input ref={inputRef} type="text"/>
})


export default function UseImperativeHandleHookDemo() {
  const inputRef = useRef();

  return (
    <div>
      <HYInput ref={inputRef}/>
      <button onClick={e => inputRef.current.focus()}>聚焦</button>
    </div>
  )
}


★useLayoutEffect  布局作用,阻塞浏览器的更新    // 稍稍阻塞浏览器的重绘,尽可能删除存在滞留隐患的监听器

useEffect 不会阻塞dom更新,dom更新完毕之后执行


export default function LayoutEffectCounterDemo() {
  const [count, setCount] = useState(10);
    //页面不会闪0,如果用useEffect ,页面是先出现0,在出现随机数
  useLayoutEffect(() => {
    if (count === 0) {
      setCount(Math.random() + 200)
    }
  }, [count]);

  return (
    <div>
      <h2>数字: {count}</h2>
      <button onClick={e => setCount(0)}>修改数字</button>
    </div>
  )
}






★自定义hoos 相同逻辑抽取到一个里面,

const Profile = (props) => {
  useLoggingLife("Profile");
  return <h2>Profile</h2>
}
//普通函数不能使用hook,只能在自定义hook中使用,use开头就代表自定义hook
function useLoggingLife(name) {
  useEffect(() => {
    console.log(`${name}组件被创建出来了`);

    return () => {
      console.log(`${name}组件被销毁掉了`);
    }
  }, []);
}


//Context共享
export function usePptContext() {
  const context = useContext(PptContext);
  return context;
}

//获取滚动位置
function useScrollPosition() {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY);
    }
    document.addEventListener("scroll", handleScroll);

    return () => {
      document.removeEventListener("scroll", handleScroll)
    }
  }, []);

  return scrollPosition;
}

const position = useScrollPosition();


★useSelector
const { banners, recommends, counter } = useSelector(state => ({
    banners: state.banners,
    recommends: state.recommends,
    counter: state.counter
  }), shallowEqual);

项目

yarn add normalize.css
reset.css
@import "~normalize.css"; //从模块里导入
@import "~antd/dist/antd.css";

配置别名: yarn add @craco/craco

"scripts": {
    "start": "craco start",
    "build": "umi build",
  },

导入文件处理:
最上面第三方的东西
中间导入功能类的东西,比如网络请求,actionCreators,utils
最后导入组件

分号尽量加上

项目里引入redux(24节,一小时)
yarn add redux react-redux redux-thunk 3个依赖
react-redux:作用把react组件和redux结合起来,其中最重要的conText 和Provider
 store/index.js 创建store 
★store

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer';

//调试工具生效 如果有就使用,否则使用compose 
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducer, composeEnhancers(
  applyMiddleware(thunk)
));

export default store;


一般会有多个reducer,需要合并


★reducer: store/ireducer.js 
import { combineReducers } from 'redux-immutable';//用redux-immutable',在useSelector中取值,用getIn方式
//import { combineReducers } from 'redux';

import { reducer as recommendReducer } from '../pages/discover/c-pages/recommend/store';
import { reducer as playerReducer } from '../pages/player/store';

const cReducer = combineReducers({
  recommend: recommendReducer,
  player: playerReducer
});

export default cReducer;

App.js
import { Provider } from 'react-redux';
import store from './store';
//Provider共享出去,然后通过connect获取store里面的state,disPatch类似的东西
  <Provider store={store}>
      <HashRouter>
        <HYAppHeader />
        <Suspense fallback={<div>page loading</div>}>
          {renderRoutes(routes)}
        </Suspense>
        <HYAppFooter />
        <HYAppPlayerBar/>
      </HashRouter>
    </Provider>


★actionCreatios:
export const getLyricAction = (id) => {
  return dispatch => {
    getLyric(id).then(res => {
      const lyric = res.lrc.lyric;
      const lyricList = parseLyric(lyric);
      dispatch(changLyricListAction(lyricList));
    })
  }
}

constants
index
reducer


redux hooks
useDispatch()

//拿到里面的值,第一个是一个回调函数
//shallowEqual性能优化,浅层比较
 // redux
  const {
    htmlName,
    currentPage,
    pageCount,
    applicationType,
  } = useSelector(
    (state: { app: Application; appstate: AppState }) => ({
      htmlName: state.app.param.htmlName,
      currentPage: state.appstate.currentPage,
      pageCount: (state.app.doc as WpDocument).pageCount,
      currentPagesSize: state.appstate.currentPagesSize,
      applicationType: state.app.param.applicationType,
    }),
    shallowEqual,
  );

★ImmutableJS //优化,提高性能,节省内存空间,只要修改会返回新的对象,旧的对象不发生变化

 const im = Immutable;
 
    // Map的使用
    // const info = {
    //   name: "kobe",
    //   age: 30,
    //   friend: {
    //     name: "james",
    //     age: 25
    //   }
    // }

    // const infoIM = im.Map(info);//改成Immutable对象

    // const obj = infoIM;
    // const infoIM2 = infoIM.set("name", "why");
    // console.log(obj.get("name"));
    // console.log(infoIM2.get("name"));

    // List的使用
    // const names = ["abc", "cba", "nba"];
    // // const arr = names;
    // // names[0] = "why";
    // // console.log(arr);
    // const namesIM = im.List(names);//改成Immutable对象
    // const arrIM = namesIM.set(0, "why");
    // console.log(namesIM.get(0));//abc 旧的
    // console.log(arrIM.get(0));//why 新的

 
 const info = {
      name: "kobe",
      age: 30,
      friend: {
        name: "james",
        age: 25
      }
    }

// const infoIM = im.Map(info);//改成Immutable对象 ,浅层转换
const infoIM = im.fromJS(info);//深层嵌套也会转换Immutable对象 ct
console.log(infoIM.get("friend"));


引入项目
//Map比fromJS性能更高
import { Map ,fromJS} from 'immutable';

import * as actionTypes from './constants';

const defaultState = Map({
  topBanners: [],

  upRanking: {},
});

function reducer(state = defaultState, action) {
  switch (action.type) {
    case actionTypes.CHANGE_TOP_BANNERS:
      return state.set("topBanners", action.topBanners);//返回新的数据
    case actionTypes.CHANGE_UP_RANKING:
      return state.set("upRanking", action.upRanking); 
    default:
      return state;
  }
}

export default reducer;

取值:
// redux hook
  const { 
    currentSong, 
    sequence, 
    lyricList,
    currentLyricIndex
  } = useSelector(state => ({
    currentSong: state.getIn(["player", "currentSong"]),
    sequence: state.getIn(["player", "sequence"]),
    lyricList: state.getIn(["player", "lyricList"]),
    currentLyricIndex: state.getIn(["player", "currentLyricIndex"])
  }), shallowEqual);
  const dispatch = useDispatch();

路由

yarn add react-router-dom

import { renderRoutes, matchRoutes } from 'react-router-config';//将所有的路由统一管理
import {
  BrowserRouter,
  Link,
  Route,
  NavLink,
  Switch,
  withRouter
} from 'react-router-dom';

组件里写法:
<NavLink exact to="/about" activeClassName="about-active">企业历史</NavLink>
<NavLink exact to="/about/culture" activeClassName="about-active">企业文化</NavLink>
<NavLink exact to="/about/contact" activeClassName="about-active">联系我们</NavLink>

<NavLink exact to="/" activeClassName="link-active">首页</NavLink>
<NavLink to="/about" activeClassName="link-active">关于</NavLink>
<NavLink to="/profile" activeClassName="link-active">我的</NavLink>
<NavLink to="/abc" activeClassName="link-active">abc</NavLink>
<NavLink to="/user" activeClassName="link-active">用户</NavLink>
<NavLink to={`/detail/${id}`} activeClassName="link-active">详情</NavLink>
<NavLink to={`/detail2?name=why&age=18`} activeClassName="link-active">详情2</NavLink>
<NavLink to={{
          pathname: "/detail3",
          search: "name=abc",
          state: info
         }} 
        activeClassName="link-active">
  详情3
</NavLink>

<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
  <Route path="/profile" component={Profile} />
  <Route path="/:id" component={User} />
  <Route path="/user" component={User} />
  <Route path="/login" component={Login} />
  <Route path="/product" component={Product} />
  <Route path="/detail/:id" component={Detail} />
  <Route path="/detail2" component={Detail2} />
  <Route path="/detail3" component={Detail3} />
  <Route component={NoMatch} />
<Switch/>

  {renderRoutes(this.props.route.routes)}// 子路由
  父页面里面写法:
  {renderRoutes(routes)}
  
export default withRouter(App);


  <BrowserRouter>
    <App/>
  </BrowserRouter>
  
  BrowserRouter使用history模式
  HashRouter使用hash模式
动态路由/$(id)

this.props.location

const routes = [
  {
    path: "/",
    exact: true,//精确匹配
    component: Home
  },
  {
    path: "/about",
    component: About,
    routes: [
      {
        path: "/about",
        exact: true,
        component: AboutHisotry
      },
      {
        path: "/about/culture",
        component: AboutCulture
      },
    ]
  },
  {
    path: "/profile",
    component: Profile
  },
  {
    path: "/user",
    component: User
  }
]

axios网络请求 封装

  • 发送请求
  • 创建实例
  • 拦截器
  • 请求封装
    get,post,head,
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

interface IResponse {
  data: any;
  errorcode: number;
  message: string;
}

const instance = axios.create({
  timeout: 60000
});

instance.interceptors.request.use((config) => {
  // 请求文档数据的拦截
  // if (config.url?.includes('index.json')) {
  //   eventBus.emit('reqSent', '请求文档数据中...');
  // }
  // 发起签批提交请求的拦截
  if (config.url?.includes('index.json')) {
    // console.log(config,'config.url')
    // eventBus.emit('reqSent', '服务器解析签批数据中...');
  }
  return config;
});

// instance.interceptors.response.use((res: AxiosResponse<IResponse>) => {
//   const { status, statusText } = res;
//   const { data, message, errorcode } = res.data;
//   if (
//     errorcode === 0 ||
//     message === '操作成功' ||
//     status.toString().startsWith('2') ||
//     statusText === 'OK'
//   ) {
//     // 延迟测试
//     // setTimeout(() => {
//     // }, 1000);
//     // eventBus.emit('reqSucceeded');
//   } else {
//     // eventBus.emit('reqFailed');
//   }
//   // console.log(res);
//   return res;
// });

//请求失败,自动重新发送请求
instance.interceptors.response.use(null, function axiosRetryInterceptor (error) {
    error.config.__retryCount = error.config.__retryCount || 0
    error.config.__retryCount += 1
    if (error.config.__retryCount >= 4) {
        console.log(error.config.__retryCount,'error.config.__retryCount')
      console.log(`url:${error.config.url}重发达到最大次数,停止重发`)
      return Promise.reject(error)
    } else {
        location.reload();
    //     console.log(`url:${error.config.url}开始重发,次数:${error.config.__retryCount},状态:${error.status},data:${JSON.stringify(error.config)}`)
    //     return new Promise(function (resolve) {
    //         return setTimeout(function () {
    //       return resolve(axios(error.config))
    //     }, 1000)
    //   })
    }
  })

// get封装
export function get(url: string, params = {}) {
  return new Promise((resolve, reject) => {
    instance({
      url: url,
      params,
      method: 'get',
    })
      .then((res) => {
        if (res.status === 200) {
          resolve(res.data);
        } else {
          reject(res);
        }
      })
      .catch((err) => {
        reject(err)
      });
  });
}

// post封装
export function post(
  url: string,
  params = {},
  data = {},
  // 进一步配置其他项
  otherConfigs = {} as AxiosRequestConfig,
) {
  return new Promise((resolve, reject) => {
    instance({
      url,
      method: 'post',
      params,
      data,
      ...otherConfigs,
    })
      .then((res) => {
        const { data } = res;
        const { status, statusText } = res;
        if (
          data.errorcode === 0 ||
          data.message === '操作成功' ||
          status.toString().startsWith('2') ||
          statusText === 'OK'
        ) {
          resolve(data);
        } else {
          reject(data);
        }
      })
      .catch((err) => {
        reject(err);
      });
  });
}

// head封装
export function head(url: string, params = {}) {
  return new Promise((resolve, reject) => {
    instance({
      url: url,
      params,
      method: 'head',
    })
      .then((res) => {
        if (res.status === 200) {
          resolve(res.data);
        } else {
          reject(res);
        }
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export default {
  get,
  post,
  head,
};

import service from './request'
  let resp =await service.get(url)

标签:return,counter,React,state,import,组件,const
From: https://www.cnblogs.com/qiyuemh/p/18222047

相关文章

  • React中常见的面试题
    本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠))喜欢的话点个赞,谢谢!1.约束性组件与非约束性组件1.1.非约束性组件非约束性组件其实就是不能控制状态的组件,比如:<inputtype="text"defaultValue="123"onChange={handleChange......
  • 深入解析Web前端三大主流框架:Angular、React和Vue
    Web前端三大主流框架分别是Angular、React和Vue。下面我将为您详细介绍这三大框架的特点和使用指南。Angular核心概念:组件(Components):组件是Angular应用的构建块,每个组件由一个带有装饰器的类、一个HTML模板、一个CSS样式表组成。组件通过输入(@Input)和输出(@Output)装饰......
  • react使用antd实现表格的时间排序
    importReactfrom'react';import{Table}from'antd';importmomentfrom'moment';constdata=[{key:'1',date:'2018-01-11T12:00:00Z',},{key:'2',date:'2......
  • React学习教程
    ReactReact前言官方文档React18中文文档1(国内社区):https://react.docschina.org/React18中文文档2(官方):https://zh-hans.reactjs.orgReact18英文文档:https://reactjs.orgReact17英文文档:https://17.reactjs.orgreact概述React是一个用于动态构建用......
  • [email protected](12)ref 转发-forwardRef
    目录1,介绍2,类组件如何使用4,应用场景-高阶组件HOC1,介绍上篇文章中提到,ref只能对类组件使用,不能对函数组件使用。而ref转发可以对函数组件实现类似的功能。使用举例:importReact,{Component}from"react";functionCompA(props,ref){return(......
  • React中何时使用memo、useCallback、useMemo以及useRef进行性能优化
    react无法做到像vue一样自动收集依赖更新(期待react19的ReactCompiler),需要开发人员手动的进行性能优化,此时memo、useCallback、useMemo、useRef就是性能优化中的重要API本文虽然介绍可应用场景,但是正常开发中,尤其是useCallback。除非遇到性能问题或者组件库封装,亦或......
  • create react app - cra系列比较
    省流版:craco目前还算在更新,其他的已经几年未更新了。虽然react官网已经不推荐cra了,但如果非要用这个系列还是推荐craco吧。GitHub-dilanx/craco:CreateReactAppConfigurationOverride,aneasyandcomprehensibleconfigurationlayerforCreateReactApp.3个月前Gi......
  • React19来了,新特性
    千呼万唤的React19来了.虽然现在还是beta版本,但是不耽误大家提前准备学习下    今天medium的订阅推送了一个React19的新特性,觉得很不错,提炼点精华的说下React19是4月25号推出的beta版,从版本号大家已经可以了解到这是React的一大版本的升级.这也标志着18版本进入......
  • React后台管理(十二)-- 页面常用hook封装 --- useSearch搜索封装
    文章目录前言一、useSearch自定义hook封装1.核心代码(1)hook文件代码+详细注释(2)使用到的store说明(3)使用到的config文件代码(4)使用到的白名单pageWhite文件代码2.使用方式(1)layout布局组件->监听并记录路由(2)搜索按钮组件->记录列表搜索的动作类型:搜索|重置(3)分页组件->记......
  • React面试题
    1.什么是React?它的特点是什么? React是一个用于构建用户界面的JavaScript库。其特点包括:使用虚拟DOM实现高效更新组件化开发,提高代码重用性和可维护性单向数据流,简化状态管理JSX语法,将组件结构和逻辑放在一起生态系统丰富,支持各种工具和库2.什么是JSX?JSX是一种JavaSc......