寻雾启示

V1

2022/09/24阅读:29主题:萌绿

React项目开发常用API

记录一下React项目开发常用API,作为后续开发的参考。

路由配置

配置文件形式

// router/index.js
import React, { lazy, Suspense } from 'react'

// Suspense配合lazy实现懒加载
const SuspenseComponent = Component => {
  return (
    <Suspense>
      <Component></Component>
    </Suspense>
  )
}

const routes = [
  {
    path: '/',
    element: SuspenseComponent(lazy(() => import('../pages/index/Index'))),
  },
  {
    path: '/login',
    element: SuspenseComponent(lazy(() => import('../pages/login/Login')))
  },
  {
    path: '/list/:b',
    element: SuspenseComponent(lazy(() => import('../pages/list/List')))
  },
  {
    path: '*',
    element: SuspenseComponent(lazy(() => import('../pages/notFound/NotFound'))),
  },
]

export default routes

标签形式

import { HashRouter, Routes, Route } from 'react-router-dom'
import Index from './pages/index/Index'
import Login from './pages/login/Login'
import NotFound from './pages/NotFound/NotFound'

<React.StrictMode>
  <HashRouter>
    <Routes>
      <Route path='/' element={<Index />}></Route>
      <Route path='/login' element={<Login />}></Route>
      <Route path='*' element={<NotFound />}></Route>
    </Routes>
  </HashRouter>
</React.StrictMode>

路由鉴权

import React, { Fragment } from 'react'
import { useRoutes, Navigate, useLocation } from 'react-router-dom'
import routes from './router'
import { getToken } from './utils/auth'

const Permission = () => {
    const token = getToken()
    const location = useLocation()
    // 没有token,且不是访问登录页,重定向到登录页
    const toLogin = !token && location.pathname !== '/login'

    function RenderRoutes() {
        return useRoutes(routes)
    }

    return (
        <Fragment>
            { toLogin ? <Navigate to="/login" replace /> : <RenderRoutes /> }
        </Fragment>
    )
}

export default Permission

路由跳转,传参

标签跳转

import { Link } from 'react-router-dom'

<Link to={{pathname: '/'}}>
    <button>跳转</button>
</Link>

useNavigate跳转

import { useNavigate } from 'react-router-dom'

const navigate = useNavigate()

/** 
  * 三种路由传参方式
  * 1、声明传参:/list/:id
  * 2、地址栏传参: /list?id=1
  * 3、state属性传参:state: { id: 1 }
  */
navigate('/List/3?a=2', {
    state: { id: 1 }
})

history跳转(前进、后退)

// history.js
import { createHashHistory } from 'history'

export default createHashHistory()


import history from './history'

history.back()

样式编写

styled-components

// App.js
import { ThemeProvider } from 'styled-components'

// 传递主题
<ThemeProvider theme={{ primaryColor: '#db3046' }}>
  <Permission />
</ThemeProvider>
// index/style.js
import styled from 'styled-components'

export default styled.div`
  height: 100vh;
  display: flex;
  flex-direction: column;
  .nav {
      height: 70px;
      padding: 0 20px;
      background-color: ${props => props.theme.primaryColor};
      display: flex;
      align-items: center;
      .title {
          text-align: left;
          flex: 1;
          font-size: 20px;
          font-weight: 600;
          color: yellow;
      }
  }
`

状态管理

创建模块

// store/features/user.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { getToken, getUserInfo, removeToken, removeUserInfo } from '../../utils/auth'
import { logout } from '../../api/login'
import history from '../../lib/history'

export const logoutAction = createAsyncThunk('user/logout', async () => {
  return await logout()
})

const slice = createSlice({
  name: 'user',
  initialState: {
    token: getToken(),
    userInfo: getUserInfo(),
  },
  reducers: {
    setToken(state, { payload }) {
      state.token = payload
    },
    setUserInfo(state, { payload }) {
      state.userInfo = payload
    },
  },
  extraReducers(builder) {
    builder.addCase(logoutAction.fulfilled, (state, { payload }) => {
      if (payload.success && payload.code === 200) {
        state.token = ''
        state.userInfo = ''
        removeToken()
        removeUserInfo()
        history.push('/login')
        location.reload()
      }
    })
  },
})

export const { setToken, setUserInfo } = slice.actions

export default slice.reducer

注册模块

// store/index.js
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './features/user'

export default configureStore({
  reducer: {
    user: userReducer
  }
})

传递状态

import { Provider } from 'react-redux'
import store from './store/index'
import App from './App'

<Provider store={store}>
  <App />
</Provider>

获取、操作状态

import { useSelector, useDispatch } from 'react-redux'
import { logoutAction } from '../../store/features/user'

const { userInfo } = useSelector(store => store.user)
const dispatch = useDispatch()

return (
  <div>
    <div>{userInfo.realName}</div>
    <button onClick={() => dispatch(logoutAction())}>登出</button>
  </div>
)

函数组件使用钩子

import React, { useState, useEffect } from 'react'

function onRequest() {}

const [number, setNumber] = useState(0)

/**
 * useEffect第二个参数不传,任意状态发生改变,都会执行
 * 传[],只在组件挂载后执行
 * 传[number],在组件挂载后和number变化后执行
 */
useEffect(() => {
    onRequest()
}, [number])

代码优化

减少重复渲染

memo

// 调用memo,当父组件重新渲染,但是props不变时,子组件读取缓存
import React, { memo } from 'react'

const Child = () => {
  return (
    <div>child</div>
  )
}

export default memo(Child)

useCallback

// 使用useCallback处理函数,当父组件重新渲染,依赖数组不变时,返回相同函数,避免触发props变化,导致子组件重新渲染
import React, { useState, useCallback } from 'react'
import Child from 'Child'

const Parent = () => {
  const [value, setValue] = useState(0)
  function sum() {
    setValue(value + 1)
  }

  const sumCall = useCallback(sum, [])
  return (
    <div>
      <div>{ value }</div>
      <Child onClick={sumCall} />
    </div>
  )
}

减少重复计算

useMemo

// 调用useMemo,当组件重新渲染时,若依赖数组不变,直接读取缓存的结果
import React, { useMemo, useState } from 'react'

const Parent = () => {
  const [value, setValue] = useState(0)
  function sum() {
    let result = 0
    for(let i = 0; i < 100000; i++) {
      result++
    }

    return result
  }

  const result = useMemo(sum, [])
  return (
    <div>
      <div>{ value + result }</div>
      <button onClick={() => setValue(value + 1)}></button>
    </div>
  )
}

分类:

前端

标签:

React.js

作者介绍

寻雾启示
V1